iT邦幫忙

0

try-catch區塊中,無法補捉NullReferenceException

c#

1.我的程式如下:

// Start a Task that throws a NullReferenceException:
            Task task = Task.Run(() => { throw null; });
            try
            {
                task.Wait();
            }
            catch (AggregateException aex)
            {
                if (aex.InnerException is NullReferenceException)
                    Console.WriteLine("Null!");
                else
                    throw;
            }

2.執行後,出現System.NullReferenceException: 'Object reference not set to an instance of an object.'的訊息.

3.想問的是,為什麼我都用try-catch了,Visual還是出現上面錯誤訊息呢?

try catch 不會改變 Visual Studio 的輸出 (這個是提示)
如果寫的是主控台程式,影響的是小黑窗的輸出
O口O iT邦新手 5 級 ‧ 2020-09-11 20:38:10 檢舉
不好意思,各位先進,我參考的是這本書的範例:C# 5.0 In a Nutshell
P.584,書上寫到,task會由呼叫wait()方法的執行緒throw exception.
可是IDE卻沒有在wait方法那邊處理exception
有程式碼我回在下方摟~
1
japhenchen
iT邦高手 1 級 ‧ 2020-09-11 15:53:09

............Task不在主執行緒裡錯誤處理.......

看更多先前的回應...收起先前的回應...

....

O口O iT邦新手 5 級 ‧ 2020-09-11 16:01:43 檢舉

感謝您的回覆,我試過你上面的程式還是一樣會出現錯誤訊息,是不是Visual哪邊的設定要更改呢?

我也被考倒了,主程序已經結束,TASK並沒有來的及在主程序結束前"出錯".....

O口O
改成這樣吧,抓的到

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

public class Example
{
    public static async Task Main()
	{
		try
		{
			await Task.Run(() => throw new Exception("DoWork failed."));
		}
		catch (Exception e)
		{
			Console.WriteLine($"Main exception occurs {e}.");
		}
		Console.Read();
	}
}


App.config也要改

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
	<runtime>
		<ThrowUnobservedTaskExceptions enabled="false" />
	</runtime>
</configuration>

別在Debug下執行就抓到了

O口O iT邦新手 5 級 ‧ 2020-09-11 20:58:57 檢舉

不好意思,各位先進,我參考的是這本書的範例:C# 5.0 In a Nutshell
P.584,書上寫到,task會由呼叫wait()方法的執行緒throw exception.
可是IDE卻沒有在wait方法那邊處理exception

O口O iT邦新手 5 級 ‧ 2020-09-11 22:21:19 檢舉

搞懂了,我一直不知道F5和Ctrl+F5的差別.謝謝指教.^^

0
glj8989332
iT邦新手 2 級 ‧ 2020-09-11 16:22:47

VS有提示{ throw null; } 內部Task跳出Exception是正確的, try/catch是包住當前執行緒的Exception, 所以外面那個抓不到.

可以改成這樣, 應該會比較清楚, 會進到裡面那層的try/catch

Task task = Task.Run(() =>
{
    try
    {
        throw null;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Task null got it");
        throw ex;
    }
});
try
{
    task.Wait();
}
catch (AggregateException aex)
{
    if (aex.InnerException is NullReferenceException)
        Console.WriteLine("Null!");
    else
        throw;
}
O口O iT邦新手 5 級 ‧ 2020-09-11 20:38:55 檢舉

不好意思,各位先進,我參考的是這本書的範例:C# 5.0 In a Nutshell
P.584,書上寫到,task會由呼叫wait()方法的執行緒throw exception.
可是IDE卻沒有在wait方法那邊處理exception

0
小魚
iT邦大師 1 級 ‧ 2020-09-11 18:15:55
  1. 你要catch整個Exception, 如果要判斷是哪種Exception可以針對Exception物件判斷.
  2. 你catch之後又throw是要丟給誰?
O口O iT邦新手 5 級 ‧ 2020-09-11 20:39:09 檢舉

不好意思,各位先進,我參考的是這本書的範例:C# 5.0 In a Nutshell
P.584,書上寫到,task會由呼叫wait()方法的執行緒throw exception.
可是IDE卻沒有在wait方法那邊處理exception

2

測了一下,程式應該是沒什麼問題

  • 首先程式會執行 thread2,這時 thread2 等於 1
  • 接著執行 thread1,這時 thread1 等於 3
  • 接著 throw null 拋出錯誤,由於這段程式區塊是由 task.Wait() 呼叫的,所以會由這裡的 try catch 捕獲。
  • 最後就進入 catch 部分執行 thread3,由於 task.Wait() 是同步呼叫,thread3 會使用 thread2 的執行續繼續執行,所以 thread3 等於 1
  • (也就是書中提到的: task會由呼叫wait()方法的執行緒throw exception)
static void Main(string[] args)
{
    Task task = Task.Run(() =>
    {
        var thread1 = Thread.CurrentThread.ManagedThreadId;
        // thread1: 3
        throw null;
    });
    try
    {
        var thread2 = Thread.CurrentThread.ManagedThreadId;
        // thread2: 1
        task.Wait();
    }
    catch (AggregateException aex)
    {
        var thread3 = Thread.CurrentThread.ManagedThreadId;
        // thread3: 1
        Console.WriteLine("Null!");
    }
}

順便測了 await 呼叫,發現幾個比較有趣的地方,分享一下

  • 流程大致上差不多,不過使用 await 拋回來的錯誤竟然不是 AggregateException,而是 NullReferenceException,害我有點懷疑人生,想說怎麼沒有 catch 進來,這部分要改成 Exception 才能成功。
  • 第二個不一樣的是 catch 內的 thread3,由於這裡的 task 和上面不一樣,是真正的使用 await 關鍵字進行非同步呼叫,所以 thread2 在執行後馬上就釋放掉了,拋回來的例外在被 await 捕捉後,會使用 Task.Run 內的執行續繼續執行,所以 thread3 會等於 3
static async Task Main(string[] args)
{
    Task task = Task.Run(() =>
    {
        var thread1 = Thread.CurrentThread.ManagedThreadId;
        // thread1: 3
        throw null;
    });
    try
    {
        var thread2 = Thread.CurrentThread.ManagedThreadId;
        // thread2: 1
        await task;
    }
    catch (Exception aex)
    {
        var thread3 = Thread.CurrentThread.ManagedThreadId;
        // thread3: 3
        Console.WriteLine("Null!");
    }
}
看更多先前的回應...收起先前的回應...
O口O iT邦新手 5 級 ‧ 2020-09-11 22:19:37 檢舉

我執行了你上面的程式,可是無法執行成功,執行時會出現錯誤訊息: '並未將物件參考設定為物件的執行個體。'
而且無法進入到catch的區塊.
想請問你是用哪種專案,App.config是不是也要像1樓說的那樣要改?

O口O iT邦新手 5 級 ‧ 2020-09-11 22:21:10 檢舉

搞懂了,我一直不知道F5和Ctrl+F5的差別.謝謝指教.^^

主控台程式 .NET Framework 4.7.2

執行時會出現錯誤訊息: '並未將物件參考設定為物件的執行個體。'

這個是 IDE 的輔助功能,出現例外會暫停程式,繼續執行就好

我要發表回答

立即登入回答