zoukankan      html  css  js  c++  java
  • 为什么避免使用Task.Wait或者Task.Result

    目标

    • 简单理解为什么不推荐在调用异步方法时,避免使用Task.Wait,或者Task.Result

    示例

    
    private void button1_Click(object sender, EventArgs e)
    {
        textBox1.Text = "button1_Click";
    
        DoSomethingAsync().Wait();
    
        textBox1.Text = "button1_Click end";
    }
    
    public async Task DoSomethingAsync()
    {
        await Task.Delay(1000);
        MessageBox.Show("DoSomethingAsyncEnd");
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
        textBox1.Text = "button2_Click";
    
        DoSomethingAsync().ConfigureAwait(false);
    
        textBox1.Text = "button2_Click end";
    }
    
    

    首先我们看上面的button1_Click代码,这种再工作中经常会碰到同事在Web应用中会写这种代码。这种代码在UI程序中会产生上面后果呢?答案是死锁,如下:

    "gif1"

    第一步我们先点击了button2可以看到并无什么异常,后面会解释,先让我们看第二步,为什么会程序卡死。button1_Click()(同步)等待DoSomethingAsync()完成,同时阻塞了同步上下文(ui主线程),当Task.Delay语句结束时(这里的结束指,遇到await立即返回调用方后),await试图在已经捕获的上下文(ui主线程,遇到await捕捉)中继续运行DoSomethingAsync()的 MessageBox.Show("DoSomethingAsyncEnd"); 但是此时上下文正在等待DoSomethingAsync()完成,此时就会互相等待(这波,这波是我等我自己)加上ui和Asp.Net上下文每次只能执行一个线程,所以就会死锁。

    但是在控制台为什么不会死锁呢?如下:

    
    static void Main(string[] args)
    {
        // null
        var syncContext = SynchronizationContext.Current;
        var taskSchedulerContext = TaskScheduler.Current;
        DoSomethingAsync().Wait();
    
    }
    public static async Task DoSomethingAsync()
    {
        await Task.Delay(1000);
        Console.WriteLine("DoSomethingAsyncEnd");
    }
    
    

    因为控制台没有SynchronizationContext上下文,如果没有上下文则会把TaskScheduler当做当前上下文继续运行,可以把这2行代码帖到上面winform里,观察到winform的不为null这个就是UI上下文,除了ui,asp.net上下文,其他很多情况下采用线程池上下文。所以捕获到上下文时候,我们的后续await后续同步的代码都想在原始的上下文中恢复运行,就比如在UI线程中调用DoSomethingAsync(),则这个MessageBox.Show("DoSomethingAsyncEnd");运行在UI线程,但是如果在线程池线程调用DoSomethingAsync(),则await后续同步的代码都在线程池线程上运行,所以需要使用ConfigureAwait(false),这个方法的意思是true尝试将延续任务(await后续同步的代码)送回原始上下文(UI)运行,false相反。

  • 相关阅读:
    知识工程及语义网技术 2020-03-19 (第一节)-构建本体
    知识工程及语义网技术 2020-03-12 (第二节)-构建本体
    知识工程及语义网技术 2020-03-12 (第二节)、RDF(S)、OWL
    知识工程及语义网技术(一)-XML、RDF(S)、OWL-2020.3.5第一节
    知识工程及语义网技术(一)-知识工程,万维网、语义网、本体工程 2020-02-20 (第一节)
    本体
    语义网技术及其应用(四)-欧石燕
    一文深度揭秘3GPP:2G/3G/4G/Pre-5G标准化制定流程是这样的
    3GPP更新5G标准时间表
    一张图了解3GPP
  • 原文地址:https://www.cnblogs.com/caiyangcc/p/14083727.html
Copyright © 2011-2022 走看看