簡體   English   中英

在主線程中捕獲異步異常

[英]Catching async exception in main thread

這是我的代碼:

using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;

namespace TestAsync
{
    class Program
    {
        private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=master;Integrated Security=True";

        static void Main(string[] args)
        {
            try
            {
                TestConnection();
            }
            catch
            {
                Console.WriteLine("Caught in main");
            }
        }

        private static async void TestConnection()
        {
            bool connected = false;

            using (var tokenSource = new CancellationTokenSource())
            using (var connection = new SqlConnection(conn))
            {
                tokenSource.CancelAfter(2000);

                try
                {
                    await connection.OpenAsync(tokenSource.Token);
                    connected = true;
                }
                catch(TaskCanceledException)
                {
                    Console.WriteLine("Caught timeout");
                }
                catch
                {
                    Console.Write("Caught in function");
                }

                if (connected)
                {
                    Console.WriteLine("Connected!");
                }
                else
                {
                    Console.WriteLine("Failed to connect...");
                    throw(new Exception("hi"));
                }
            }
        }
    }
}

輸出為:

Caught timeout
Failed to connect...

但是隨后我的程序以未處理的異常終止。 相反,我希望程序在主線程中處理拋出的異常,並Caught in main打印出Caught in main 我該如何工作?

編輯

這是我更新后的代碼,可以按照我想要的方式工作:

using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;

namespace TestAsync
{
    class Program
    {
        private const string conn = "Data Source=UNREACHABLESERVER;Initial Catalog=MyFiles;Integrated Security=True";

        static void Main(string[] args)
        {
            try
            {
                TestConnection().Wait();
            }
            catch
            {
                Console.WriteLine("Caught in main");
            }

            Console.ReadLine();
        }

        private static async Task TestConnection()
        {
            using (var tokenSource = new CancellationTokenSource())
            using (var connection = new SqlConnection(conn))
            {
                tokenSource.CancelAfter(2000);
                await connection.OpenAsync(tokenSource.Token);
            }
        }
    }
}

這是不可能的。 一旦遇到第一次await您對TestConnection()調用將返回(因此將繼續在主線程上執行)。 您的catch塊和引發異常將在另一個線程上執行,並且不會被主線程觀察到。

這只是避免async void一個原因。 如果您需要編寫async void函數,則它必須完全獨立(包括錯誤處理邏輯)。 您最好編寫一個async Task函數。 最簡單的方法是將Main方法中的調用修改為此:

TestConnection().Wait()

當然,這將導致主線程在執行函數時阻塞(在編譯之前,您還必須將簽名更改為async Task )。

暫無
暫無

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

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