1. 程式人生 > >C#中如果用await關鍵字來await一個為null的Task物件會丟擲異常

C#中如果用await關鍵字來await一個為null的Task物件會丟擲異常

await & async模式是C#中一個很重要的特性,可以用來提高非同步程式(多執行緒程式)的執行效率。但是如果嘗試用await關鍵字來await一個為null的Task物件,會導致程式丟擲NullReferenceException異常。

 

新建一個.NET Core控制檯專案,貼入如下程式碼:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AwaitNull
{
    class Program
    {
        /// <summary>
/// AwaitNullTask方法中的程式碼會await一個為null的Task t,這樣做會丟擲NullReferenceException異常 /// </summary> static async Task AwaitNullTask() { Task t = null;//宣告一個為null的Task物件t try { await t;//await為null的Task物件t,會導致這裡丟擲NullReferenceException異常
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Await finished...");//由於上面丟擲了異常,這裡的Console.WriteLine不會被執行 } catch(NullReferenceException e) { //輸出異常資訊 Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : AwaitNullTask threw Exception : {e.GetType().ToString()}
"); Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Exception message : {e.Message}"); throw;//catch後繼續丟擲NullReferenceException異常到AwaitNullTask方法的外部 } } static void Main(string[] args) { Task taskReturned = AwaitNullTask();//很有意思的是雖然AwaitNullTask方法內部丟擲了NullReferenceException異常,但是其並不會影響AwaitNullTask方法外部的方法,就好像AwaitNullTask方法是在另外一個執行緒上執行的一樣,但是本例中我們沒有用Task來啟動任何執行緒,可以看到本例中所有Console輸出的資訊中Thread id都相同,是在同一個執行緒上 Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : taskReturned status is : {taskReturned.Status.ToString()}");//輸出AwaitNullTask方法返回的Task物件taskReturned的Status,由於AwaitNullTask方法內部丟擲了異常,所以Task物件taskReturned的Status為Faulted Console.WriteLine(); Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Press any key to quit..."); Console.ReadKey(); } } }

輸出結果如下:

我們可以看到AwaitNullTask方法中由於await了一個為null的Task物件,丟擲了NullReferenceException異常,但是有意思的是,AwaitNullTask方法表現出的行為是貌似執行在另一個執行緒上一樣,其丟擲的NullReferenceException異常並不會影響到Main方法,但實際上Main方法和AwaitNullTask方法都是由同一個執行緒執行的。