当前位置: 移动技术网 > IT编程>开发语言>.net > 【C#】await & Result DeadLock

【C#】await & Result DeadLock

2019年04月19日  | 移动技术网IT编程  | 我要评论

江财人在深圳,阿衰全集动画片,炎狼学苑

随意使用异步的await和result,被弄得欲仙欲死,然后看了 ,稍许明白,翻译然后加上自己的理解以加深印象。

会死锁的两个例子

ui例子

    public static async task<jobject> getjsonasync(uri uri)
    {
        using (var client = new httpclient())
        {
            var jsonstring = await client.getstringasync(uri);
            return jobject.parse(jsonstring);
        }
    }

    // my "top-level" method.
    public void button1_click(...)
    {
        var jsontask = getjsonasync(...);
        textbox1.text = jsontask.result;
    }

** asp.net例子**

    public static async task<jobject> getjsonasync(uri uri)
    {
        using (var client = new httpclient())
        {
            var jsonstring = await client.getstringasync(uri);
            return jobject.parse(jsonstring);
        }
    }

    // my "top-level" method.
    public class mycontroller : apicontroller
    {
        public string get()
        {
            var jsontask = getjsonasync(...);
            return jsontask.result.tostring();
        }
    }

死锁的原因

await 一个task后,当task完成后将继续一个context。

ui例子的content是 ui content,asp.net例子的content是request content。在任何时候,这两个content只能属于一个线程,是不能被具体的线程捆绑(tied)。这个有趣或者恶心的特色没被官方文档说明,只在。

上面两个例子的运行过程是:

  1. 在ui/asp.net context,调用getjsonasync方法;
  2. 在ui/asp.net context,getjsonasync方法调用httpclient.getstringasync开始一个rest请求;
  3. getstringasync返回一个未完成的task,表示rest请求没有完成;
  4. getjsonasync等待getstringasync返回的task。当前context被捕获(保存),当前context在getjsonasync完成时将被调用。getjsonasync返回一个未完成的task,表示getjsonasync方法未完成;
  5. jsontask.result同步阻塞getjsonasync返回的任务,即阻塞context;
  6. ...然后,rest请求完成了,然后通知getstringasync方法;
  7. getstringasync准备继续任务,他等待context可用,然后他可以在context运行;
  8. 死锁!jsontask.result阻塞了context线程,等待getstringasync完成,getstringasync等待context空闲,然后它可以完成。

防止死锁

两点经验:

  1. 异步方法中,尽可能添加configureawait(false)
  2. 别阻塞;使用 async

根据第一点经验:
var jsonstring = await client.getstringasync(uri);
改成
var jsonstring = await client.getstringasync(uri).configureawait(false);

根据第二点经验,调用异步方法的代码如下:

    public async void button1_click(...)
    {
        var json = await getjsonasync(...);
        textbox1.text = json;
    }

    public class mycontroller : apicontroller
    {
        public async task<string> get()
        {
            var json = await getjsonasync(...);
            return json.tostring();
        }
    }

await 是一个异步等待
.result是一个同步等待

同步等待在控制台程序、单元测试中不会死锁

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网