随笔 - 149  文章 - 8  评论 - 248  阅读 - 21万

async await 死锁简单分析

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

死锁代码

复制代码
        private void Button_Click(object sender, EventArgs e)
        {
            var jsonTask = GetJsonAsync(new Uri("https://www.toolhelper.cn/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.toolhelper.cn/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.toolhelper.cn/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.
        }

 

posted on   几度夕阳红了  阅读(389)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示