zoukankan      html  css  js  c++  java
  • 异步编程异常和死锁处理

    在.NET异步编程中,通常使用async和await这对黄金搭档,返回类型使用Task或Task<T>。在方法前面加async表示这个方法运行异步,在方法内使用await表示执行一个异步等待。

    下面是一个简单例子:

            static void Main(string[] args)
    
            {
    
                Doth();
    
                Console.ReadKey();
    
            }
    
            static async Task Doth()
    
            {
    
                int i = 2;
    
                await Task.Delay(TimeSpan.FromSeconds(2));
    
                i += 2;
    
                await Task.Delay(TimeSpan.FromSeconds(2));
    
                Console.WriteLine(i);
    
            }
    

    当执行DoSth方法,第一个await执行一个异步等待,当执行完成,就继续执行下面的代码。在async修饰的方法内部,一个await就是一个异步等待,可以包含多个await, 每一个await执行完毕才会执行它后面的代码,也就是说在DoSth内部是同步的。

    各个await在哪个线程中运行呢?

     

    默认情况下是在当前线程中运行,不过.NET提供了ConfigureAwait方法,用来设置await在哪个线程中运行。

            static async Task Doth()
    
            {
    
                int i = 2;
    
                await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
    
                i += 2;
    
                await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
    
                Console.WriteLine(i);
    
            }

    以上,当第一个await运行在控制台项目所在的线程中,第二个await将在线程池上运行。

    我们无法保证每个await不会抛出异常,通常按如下的方式捕获异常。

    async Task DosthAsync()
    
    {
    
        try
    
        {
    
            await PossibleExceptionAsync();
    
        }
    
        catch(NotSuppotedException ex)
    
        {
    
            LogException(ex);
    
            throw;
    
        }
    
    }

    由于抛出的异常会放在Task对象中,所以也可以这么写:

    async Task DosthAsync()
    
    {
    
        Task task = PossibleExceptionAsync();
    
        try
    
        {
    
            await task;
    
        }
    
        cach(NotSupportedException ex)
    
        {
    
            LogException(ex);
    
            throw;
    
        }
    
    }

    异步编程也会出现死锁。

    async Task DoSthSync()
    
    {
    
        await Task.Delay(TimeSpan.FromSeconds(1));
    
    }
    
    void FirstThing()
    
    {
    
        Task tak = DoSthSync();
    
        task.Wait();
    
    }
    

    以上,如果调用FirstThing方法就会出现死锁的情况。

    →执行FirstThing方法
    →在FirstThing方法内部执行DoSthSync方法,这时,当前上下文线程被阻塞
    →来到DoSthSync方法中,其中的await试图捕获当前上下文线程,而当前的上下线程已经被阻塞在那里了,造成死锁。

    死锁如何解决死锁呢?

     

    可以在DoSthSync内部不使用当前上下文线程,改用线程池中的线程,修改如下:

    async Task DoSthSync()
    
    {
    
        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
    
    }

    或者,让FirstThing变成一个异步方法。修改如下:

    async Task DoSthSync()
    
    {
    
        await Task.Delay(TimeSpan.FromSeconds(1));
    
    }
    
    async Task FirstThing()
    
    {
    
        await DoSthSync();
    
    }
    
  • 相关阅读:
    从多渠道打包与友盟统计有这一篇就够了
    多渠道打包
    studio构建错误Element uses-permission#android.permission.ACCESS_NETWORK_STATE at AndroidManifest.xml:38:5-79 dupli
    ADB命令与monkey
    正则表达式和文本挖掘(Text Mining)
    一步一步教你使用Git
    Android常见开源解决方案
    Android Intent到底能做些什么
    支付宝集成
    Theano 学习三 conv2d
  • 原文地址:https://www.cnblogs.com/darrenji/p/4710425.html
Copyright © 2011-2022 走看看