Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何调用异步方法并从中更新UI?_C#_.net_User Interface_Task Parallel Library_Async Await - Fatal编程技术网

C# 如何调用异步方法并从中更新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

最近我已经完成了PagedDagRidView自定义控件的设计,它工作得很好,但现在我想改进它的性能

如何?嗯,我在显示新页面时看到一些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
    }
}

我正在尝试做什么(使用异步/等待模式): 异步方法DoPaging暂停,直到等待“LoadDataOnGrid”完成,这样UI线程就不会被阻塞,而是异步的。


我刚刚开始学习异步-等待编码,任何更正或建议都将不胜感激。

只需将
async
添加到按钮单击事件处理程序方法中,并等待调用
DoPaging()


这样做与您给出警告的方式(事实上,这也是为什么会给出警告)不同之处在于,如果您在事件处理程序中调用
DoPaging()
后添加了任何代码,那么现在将在任务完成后发生,而before则会在调用后立即执行。

这两者之间有很大区别:

private void btnGoNextPage(object sender, EventArgs e)
{
    DoPaging();
}

异常处理。如果前者引发异常,则可能会发生两种情况:

  • 如果您使用的是.NET 4.0,被吞没的任务将从
    终结器
    线程重新抛出,并将导致应用程序崩溃
  • 如果您使用的是.NET 4.5,则该任务将被吞并,并且不会被注意到,将根本不会被重新抛出,因此可能会在您不知道的损坏状态下进入您的应用程序
  • 在后一个示例中,异常将传播到
    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();
    }