c# - 在主线程中捕获异步异常

标签 c# sql asynchronous async-await

这是我的代码:

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。我怎样才能让它发挥作用?

编辑

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

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 block 和抛出异常将在另一个线程上执行并且不会被主线程观察到。

这只是应该避免 async void 的原因之一。如果您需要编写一个 async void 函数,它必须是完全独立的(包括错误处理逻辑)。您最好编写一个 async Task 函数。最简单的方法是将 Main 方法中的调用修改为:

TestConnection().Wait()

当然,这会导致主线程在执行该函数时阻塞(您还必须在编译之前将签名更改为 async Task)。

关于c# - 在主线程中捕获异步异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16765424/

相关文章:

c# - 策略模式还是命令模式?

c# - 如何抓取 JavaScript WebBrowser 更新的内容

mysql - 将 .sql 查询保存为 .sql 文本文件

c# - 如何获取有关事件的调试信息

c# - 将 mask 应用于位图并在运行时生成合成图像

sql - 使用包含在 postgres psql 命令中的文件设置 search_path

c# - IDENTITY_INSERT 设置为 OFF 时出现问题? :-/

asynchronous - 由 webfontloader 加载的谷歌字体呈现阻塞

c# - 如何使 MvvmLight 命令异步?

excel - 如何VBA发送异步XMLHTTP请求?