• c# async/await异步编程死锁的问题


    在异步编程中,如果稍有不注意,就会造成死锁问题。何为死锁:即两个以上的线程同时争夺被互相锁住的资源,两个都不放手。

    在UI或asp.net中,容易造成死锁的代码如下所示:

            private void btnSet_Click(object sender, EventArgs e) {
                Task<int> task= DelayAsync();
                //在同步代码中有wait同步等待函数
                task.Wait();           
                this.Text = "测试";
            }
    
            private async Task<int> DelayAsync() {        
                //在异步方法中,有await异步等待函数   
                await Task.Delay(1000);          
                return 100;           
            }

    当执行btnSet_Click方法时,程序就会造成死锁,this.Text="测试" 这一行代码永远都不会执行。

     为何会造成死锁?首先,task.Wait()方法造成了当前主线程被阻塞,其次,DelayAsync方法中的Task.Delay(1000)(由挂起到激活状态)运行结束时会捕获当前的上下文线程,而当前的上下文线程已经被阻塞,故造成死锁。

    解决的方法有两个:

    1、将btnSet_click变为异步方法,全部采用异步等待的方式;

            private async void btnSet_Click(object sender, EventArgs e) {            
                int result=await DelayAsync();
                this.Text = result.ToString();            
            }
    
            private async Task<int> DelayAsync() {            
                await Task.Delay(1000);
                return 100;
            }

    2、在异步方法中使用Task.ConfigureAwait(false),不将await产生的延时任务送回到原始上下文线程中,即不会去捕获原始上下文,并在其新开辟的线程中结束其代码的运行,如下面的代码。

    备注:如果是这种方式,则在异步方法的Task.ConfigureAwait(false)语句之后的代码块中,获取不了原始上下文的某些变量,容易造成NullReferenceException空值引用异常。

            private async void btnSet_Click(object sender, EventArgs e) {
                Task<int> task = DelayAsync();            
                task.Wait();
                this.Text = task.Result.ToString();
            }
    
            private async Task<int> DelayAsync() {           
                await Task.Delay(1000).ConfigureAwait(false);
                return 100;
            }
  • 相关阅读:
    .Net中的设计模式——Decorator模式
    PetShop的系统架构设计
    PetShop数据访问层之消息处理
    对象的封装与C#的类
    Flash/Flex学习笔记(46):正向运动学
    Flash/Flex学习笔记(43):动量守恒与能量守恒
    win7下恢复“经典任务栏”/“快速启动栏”,关闭“窗口自动最大化”
    Flash/Flex学习笔记(50):3D线条与填充
    图片的javascript延时加载
    Flash/Flex学习笔记(51):3维旋转与透视变换(PerspectiveProjection)
  • 原文地址:https://www.cnblogs.com/williamwsj/p/8529203.html
Copyright © 2020-2023  润新知