这是我的代码:
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/