winfrom 多线程卡死问题

原因分析

        我们在执行一下代码的时候会发现程序卡死了,首先winform项目中能够修改控件的必须是UI线程,主线程遇到await返回后会将下面未执行的代码打包交给线程池,由线程池分配线程再处理,而因为winformUI线程的特殊性,丢给线程池后会有上下文环境的问题,而这个上下文环境的问题只有主线程会涉及到,所以打包后的内容优先由主线程来执行。而这个特殊性导致winform在await之后运行的线程一定是UI线程。

private void btnSync_Click(object sender, EventArgs e)
{
    Console.WriteLine($"This is btnSync_Click Start,ThreadId={Thread.CurrentThread.ManagedThreadId}");

    var task = this.CalculationAsync(1_000_000);
    task.Wait();
    long lResult = task.Result;//同步阻塞,主线程在等结果

    //long lResult = this.GetCalculationAsync(1_000_000);//换个线程去调用async方法,有点恶心

    Console.WriteLine($"This is btnSync_Click   End,ThreadId={Thread.CurrentThread.ManagedThreadId}");

    this.lblSync.Text = lResult.ToString();
}

private async Task<long> CalculationAsync(long total)
{
    var result = await Task.Run(() =>
    {
        Console.WriteLine($"This is CalculationAsync Start,ThreadId={Thread.CurrentThread.ManagedThreadId}");
        long lResult = 0;
        for (int i = 0; i < total; i++)
        {
            lResult += i;
        }
        Console.WriteLine($"This is CalculationAsync   End,ThreadId={Thread.CurrentThread.ManagedThreadId}");

        return lResult;
    });

    return result;//await后面的代码,会要求主线程来执行
}

解决方式

一 添加 async await

private async void btnAsync_Click(object sender, EventArgs e)
 {
      Console.WriteLine($"This is btnAsync_Click Start,ThreadId={Thread.CurrentThread.ManagedThreadId}");

      long lResult = await this.CalculationAsync(1_000_000);

      Console.WriteLine($"This is btnAsync_Click   End,ThreadId={Thread.CurrentThread.ManagedThreadId}");

      this.lblAsyncResult.Text = lResult.ToString();//必须是UI线程,更新能成功是因为winform的UI线程特殊性,await之后的线程一定是UI线程
}

二 添加同步方法去调用异步方法

private long GetCalculationAsync(long total)
{
    var taskLong = Task.Run(() =>
     {
         var task = this.CalculationAsync(total);
         long lResult = task.Result;//子线程
         return lResult;
     });
    return taskLong.Result;//主线程在等Result
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值