最近我已经完成了PagedDataGridView自定义控件的设计,它运行得很好,但现在我想提高它的性能。
怎么样?好吧,我在显示新页面时看到了一些UI阻止 简而言之,这就是:
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
}
}
我想做的事情(使用async / await模式):
异步方法DoPaging暂停,直到等待'LoadDataOnGrid'完成后,UI线程不会被阻塞,这是异步的
// Class that handles paging methods, variables,
// also offers navigation controls, such as buttons, labels, etc.
internal class Paging
{
// Represents the method that code client uses to load its own data
public Action LoadDataClientMethod;
// HERE:
private async Task DoPaging()
{
// some calculations
if (LoadDataClientMethod != null)
{
// I realizad that calling Run method, runs it out of context
// How to run this method, and update the UI
await Task.Run(() => LoadDataClientMethod());
}
// Update controls, showing current page, etc
UpdateUI();
}
// Navigation buttons
private void btnGoNextPage(object sender, EventArgs e)
{
// go next page calculations
// Then how to call the async method
DoPaging(); // -> doing this, VS shows a warning:
/* Because this call is not awaited, the current method
continues to run before the call is completed */
}
}
我刚刚开始学习异步 - 等待编码,任何更正或建议将不胜感激,谢谢。
答案 0 :(得分:1)
只需将async
添加到按钮点击事件处理程序方法,然后等待对DoPaging()
的调用:
private async void btnGoNextPage(object sender, EventArgs e)
{
await DoPaging();
}
像这样做而不是你的方式给出warning(实际上是为什么给出警告)之间的区别在于,如果你在调用{{1}之后添加了任何代码在事件处理程序中,它现在将在任务完成后发生,而在调用之后立即执行。
答案 1 :(得分:1)
之间存在很大差异:
private void btnGoNextPage(object sender, EventArgs e)
{
DoPaging();
}
和
private async void btnGoNextPage(object sender, EventArgs e)
{
await DoPaging();
}
异常处理。如果前者抛出异常,可能会发生两件事:
Finalizer
主题重新抛出,并导致您的应用程序崩溃 在后一个示例中,异常将传播到await
点,您可以通过添加try-catch
块来优雅地处理它。
作为旁注,我在评论中告诉你正在做什么样的工作阻塞你的UI线程,你说你正在调用你的数据库来检索数据。
针对数据库进行的工作是IO绑定工作,并且大多数提供程序公开异步端点以访问数据,例如实体框架,ADO.NET等。您可以通过不使用任何线程池线程来执行自然异步行为。适合你(在你的例子中使用Task.Run
)。当你“一直异步”时,你可以这样做,你的数据库查询可以与await
关键字一起使用。这样,当查询检索数据时,调用查询的线程(在您的示例中,UI线程)被释放并且可以执行更多工作,因此您的UI将保持响应。
我建议你研究一下,看看你的数据库提供者是否有那些异步端点。