zoukankan      html  css  js  c++  java
  • async await 死锁简单分析

    虽然写了很多asyncawait代码,有时候由于一些原因,还是发生了死锁,所以这次就简单的分析下。

    死锁代码

            private void Button_Click(object sender, EventArgs e)
            {
                var jsonTask = GetJsonAsync(new Uri("https://www.yishasoft.com/admin/SystemManage/DataDict/GetDataDictListJson"));
                string result = jsonTask.Result.ToString(); // 步骤1.主线程在这里被 jsonTask.Result 阻塞,直到 jsonTask 完成
            }
    
            public static async Task<JObject> GetJsonAsync(Uri uri)
            {
                // 步骤2.当前所在的线程是主线程
                using (var client = new HttpClient())
                {
                    var jsonString = await client.GetStringAsync(uri);
                    // 步骤3.GetStringAsync 执行完成后,返回步骤2所在的线程(主线程),但是主线程在步骤1已经被阻塞
                    return JObject.Parse(jsonString);
                }
            }

    改进一,加上 ConfigureAwait(false)

            private void Button_Click(object sender, EventArgs e)
            {
                var jsonTask = GetJsonAsync(new Uri("https://www.yishasoft.com/admin/SystemManage/DataDict/GetDataDictListJson"));
                string result = jsonTask.Result.ToString(); // 步骤1.主线程在这里被 jsonTask.Result 阻塞,直到 jsonTask 完成
            }
    
            public static async Task<JObject> GetJsonAsync(Uri uri)
            {
                // 步骤2.当前所在的线程是主线程
                using (var client = new HttpClient())
                {
                    var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);
                    // 步骤3.GetStringAsync 执行完成后,根据ConfigureAwait(false),此行后面的代码不返回到步骤2所在的线程(主线程)
                    return JObject.Parse(jsonString);
                }
            }

    改进二,使用标准写法

            private async void Button_Click(object sender, EventArgs e)
            {
                var jsonTask = await GetJsonAsync(new Uri("https://www.yishasoft.com/admin/SystemManage/DataDict/GetDataDictListJson")); // 步骤1.这种写法,主线程不会被阻塞
                string result = jsonTask.ToString();
            }
    
            public static async Task<JObject> GetJsonAsync(Uri uri)
            {
                // 步骤2.当前所在的线程是主线程或者是其他线程
                using (var client = new HttpClient())
                {
                    var jsonString = await client.GetStringAsync(uri);
                    // 步骤3.GetStringAsync 执行完成后,后面的代码返回到步骤2所在的线程
                    return JObject.Parse(jsonString);
                }
            }

    如果处理任务需要在界面上显示加载中(spinning)图片,使用async仍然会阻塞主线程,一种解决的办法如下。

            private async Task LoadData()
            {
                await Task.Run(() =>
                {
                    //Work done here
                });
                // Update UI if necessary.
            }

     

  • 相关阅读:
    Mysql-学习笔记(==》事件 十二)
    Mysql-学习笔记(==》触发器 十一)
    Mysql-学习笔记(==》函数的建立与使用 十)
    Mysql-学习笔记(==》存储过程 九)
    Mysql-学习笔记(==》常用函数 八)
    Mysql-学习笔记(==》增删主键建立索引 七)
    Mysql-学习笔记(==》约束 六)
    Mysql-学习笔记(==》集合函数与分组四)
    Mysql-学习笔记(==》连接查询_高级查询五)
    Unity3D优化技巧系列七
  • 原文地址:https://www.cnblogs.com/lhking/p/13235826.html
Copyright © 2011-2022 走看看