簡體   English   中英

異步/等待異常處理

[英]Async/Await exception handling

我的問題是基於文章異步編程最佳實踐

所以我有這個代碼

    async static void AsyncVersion()
    {
        Stopwatch sw = Stopwatch.StartNew();
        string url1 = "http://rsdn.ru";
        string url2 = "http://gotdotnet.ru";
        string url3 = "http://blogs.msdn.com";

        var webRequest1 = WebRequest.Create(url1);
        Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
            Thread.CurrentThread.ManagedThreadId);
        ...

所以這段代碼會引發異常,例如當我沒有inet連接時。 因此,當我遵循msdn的指導並將方法的簽名更改為Task(而不是void)時,但是在此之后,它吞噬了所有異常,但是嘿,外部catch塊無法處理。

整個代碼如下

using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication8
{
    class Program
    {
        async static Task AsyncVersion()
        {
            Stopwatch sw = Stopwatch.StartNew();
            string url1 = "http://rsdn.ru";
            string url2 = "http://gotdotnet.ru";
            string url3 = "http://blogs.msdn.com";

            var webRequest1 = WebRequest.Create(url1);
            Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);

            var webResponse1 = await webRequest1.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url1,
                webResponse1.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);

            var webRequest2 = WebRequest.Create(url2);
            Console.WriteLine("Before webRequest2.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);

            var webResponse2 = await webRequest2.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url2,
                webResponse2.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);

            var webRequest3 = WebRequest.Create(url3);
            Console.WriteLine("Before webRequest3.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);
            var webResponse3 = await webRequest3.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url3,
                webResponse3.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);
        }
        static void Main(string[] args)
        {

            try
            {
                Console.WriteLine("Main thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Task task = new Task(() => AsyncVersion());
                task.Start();
                Console.WriteLine("Right after AsyncVersion() method call");
                //Ожидаем завершения асинхронной операции
                task.Wait();
                Console.WriteLine("Asyncronous task finished!");

            }
            catch (Exception e)
            {
                //Все исключения в TPL пробрасываются обернутые в AggregateException
                Console.WriteLine("Exceptopn: {0}", e.Message);
            }
            Console.ReadLine();
        }
    }
}

舊版本:

using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication8
{
    class Program
    {
        async static void AsyncVersion()
        {
            Stopwatch sw = Stopwatch.StartNew();
            string url1 = "http://rsdn.ru";
            string url2 = "http://gotdotnet.ru";
            string url3 = "http://blogs.msdn.com";

            var webRequest1 = WebRequest.Create(url1);
            Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);

            var webResponse1 = await webRequest1.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url1,
                webResponse1.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);

            var webRequest2 = WebRequest.Create(url2);
            Console.WriteLine("Before webRequest2.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);

            var webResponse2 = await webRequest2.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url2,
                webResponse2.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);

            var webRequest3 = WebRequest.Create(url3);
            Console.WriteLine("Before webRequest3.GetResponseAsync(). Thread Id: {0}",
                Thread.CurrentThread.ManagedThreadId);
            var webResponse3 = await webRequest3.GetResponseAsync();
            Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url3,
                webResponse3.ContentLength, sw.ElapsedMilliseconds,
                Thread.CurrentThread.ManagedThreadId);
        }
        static void Main(string[] args)
        {

            try
            {
                Console.WriteLine("Main thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Task task = new Task(AsyncVersion);
                task.Start();
                Console.WriteLine("Right after AsyncVersion() method call");
                //Ожидаем завершения асинхронной операции
                task.Wait();
                Console.WriteLine("Asyncronous task finished!");

            }
            catch (System.AggregateException e)
            {
                //Все исключения в TPL пробрасываются обернутые в AggregateException
                Console.WriteLine("AggregateException: {0}", e.InnerException.Message);
            }
            Console.ReadLine();
        }
    }
}
new Task(() => AsyncVersion())

這是有問題的部分。 Task構造函數不了解async ,因此它將忽略從AsyncVersion返回的Task (事實上​​,您必須使用lambda而不是直接編寫AsyncVersion應該已經使您警惕發生了奇怪的事情。)

您有幾種解決方法(最后選擇最好):

  1. 也將Task<Task>Wait()用於內部Task

     Task<Task> task = new Task<Task>(AsyncVersion); task.Start(); task.Result.Wait(); 
  2. 使用Unwrap()來改變Task<Task>Task表示兩個Task S:

     Task<Task> task = new Task<Task>(AsyncVersion); task.Start(); task.Unwrap().Wait(); 
  3. 使用Task.Run() ,它確實了解async

     Task task = Task.Run(() => AsyncVersion()); task.Wait(); 
  4. 根本不啟動Task ,只需調用async方法:

     Task task = AsyncVersion(); task.Wait(); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM