C# 如何调用异步方法并从中更新UI?
最近我已经完成了PagedDagRidView自定义控件的设计,它工作得很好,但现在我想改进它的性能 如何?嗯,我在显示新页面时看到一些UI阻塞。C# 如何调用异步方法并从中更新UI?,c#,.net,user-interface,task-parallel-library,async-await,C#,.net,User Interface,Task Parallel Library,Async Await,最近我已经完成了PagedDagRidView自定义控件的设计,它工作得很好,但现在我想改进它的性能 如何?嗯,我在显示新页面时看到一些UI阻塞。 简言之,这是: public class PagedDataGridView() : UserControl { Paging paging = new Paging(); public PagedDataGridView() { paging.LoadDataClientMethod = LoadDataO
简言之,这是:
public class PagedDataGridView() : UserControl
{
Paging paging = new Paging();
public PagedDataGridView()
{
paging.LoadDataClientMethod = LoadDataOnGrid;
}
private void LoadDataOnGrid()
{
// Some heavy set data source here, using functions from 'paging' object
}
}
我正在尝试做什么(使用异步/等待模式): 异步方法DoPaging暂停,直到等待“LoadDataOnGrid”完成,这样UI线程就不会被阻塞,而是异步的。
我刚刚开始学习异步-等待编码,任何更正或建议都将不胜感激。只需将
async
添加到按钮单击事件处理程序方法中,并等待调用DoPaging()
:
这样做与您给出警告的方式(事实上,这也是为什么会给出警告)不同之处在于,如果您在事件处理程序中调用
DoPaging()
后添加了任何代码,那么现在将在任务完成后发生,而before则会在调用后立即执行。这两者之间有很大区别:
private void btnGoNextPage(object sender, EventArgs e)
{
DoPaging();
}
及
异常处理。如果前者引发异常,则可能会发生两种情况:
终结器
线程重新抛出,并将导致应用程序崩溃await
点,您可以通过添加try-catch
块优雅地处理它
作为旁注,我在评论中问过您,正在做什么样的工作来阻止您的UI线程,您说您正在调用数据库来检索数据。
针对数据库所做的工作是IO绑定的工作,大多数提供程序都会公开异步端点来访问数据,如Entity Framework、ADO.NET等。您可以通过不使用任何线程池线程来利用这种自然异步行为(使用Task.Run
,就像您在示例中所做的那样)。您可以在“一路异步”时执行此操作,并且您的数据库查询可以与wait
关键字一起使用。这样,当查询检索数据时,调用查询的线程(在您的示例中为UI线程)将被释放,并且可以做更多的工作,因此您的UI将保持响应
我建议您研究一下,看看您的数据库提供程序是否有这些异步端点。
我想改进它的性能。
-您可能想看看。基本上,你是在逆风而行,使用过时的技术,并期望它提供世界级的功能和性能。好吧,这个项目已经在运行和工作,现在改变它有点太晚了。下周我有一些空闲时间,所以我将用WPF开始一个新版本,在看了这段视频后我非常兴奋,谢谢。“看了这段视频后我非常兴奋”-这段视频真的没什么大不了的。你的LoadDataToGrid
方法是做IO绑定的工作(从磁盘/网络获取数据)还是CPU绑定的工作(计算等)?@YuvalItzchakov从BLL接口(数据库应用程序)获取数据,这不等于没有像op在代码中那样等待吗(这意味着两者都是正确的和等效的,因为事件处理程序不会阻止UI)?@mclaassen哦,我明白了,有了wait
all after DoPaging()将不得不等待。感谢您对LoadDataOnGrid
方法所做工作的详细回答,实际检索到的数据属于由BLL接口(n层应用程序)发送的IEnumerable
集合,此集合在PagedDataGridView
类中进行了一些处理和数据格式化,对数据库没有真正的直接工作。这种处理会阻塞UI,这并不重要,但可能会很烦人,我确信可以避免进行异步工作;经过一些测试,最差的响应可能需要3000-400次0ms,这就是分页的原因。所以工作主要是CPU受限的,这没关系。使用任务.Run
应该可以很好地工作,但请注意我文章的第一部分,关于例外情况。好吧,我现在的问题是,在执行任务时UI不会更新。在调用DoPaging
时运行?你是任务吗。Run
正在抛出例外?
private async void btnGoNextPage(object sender, EventArgs e)
{
await DoPaging();
}
private void btnGoNextPage(object sender, EventArgs e)
{
DoPaging();
}
private async void btnGoNextPage(object sender, EventArgs e)
{
await DoPaging();
}