下面的代码没有捕获我的OperationCancelEException,它是通过调用抛出的ct.ThrowIfCancellationRequested
.
public partial class TitleWindow : Window, IAsyncInitialization
{
public Task Initialization{get; private set;}
CancellationTokenSource cts;
public TitleWindow()
{
InitializeComponent();
cts = new CancellationTokenSource();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
cts.Cancel();
Initialization = GetCancelExceptionAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled!");
}
}
public async Task GetCancelExceptionAsync(CancellationToken ct)
{
await Task.Delay(1000);
ct.ThrowIfCancellationRequested();
}
}
但是如果我更换我的Window_Loaded
方法与以下(使其异步并等待我的异步方法的调用),异常被捕获。
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
cts.Cancel();
await GetCancelExceptionAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled!");
}
}
为什么我的第一种方法不起作用?异常是否未正确传播到正确的同步上下文?
我试图使用The Asynchronous Initialization Pattern
描述于斯蒂芬·克利里斯的博客文章 http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html以便稍后能够等待在构造函数中启动的任务(并且为了使其与我的第二个示例相当,我使用了(async
) Window_Loaded
立即等待方法的事件,就像在 a 中向我建议的那样上一个问题 https://stackoverflow.com/questions/28606556/async-await-am-i-using-the-wrong-synchronisation-context)。然后我想提供一个选项来取消我在构造函数中启动的异步方法,我目前陷入困境,因为异常处理没有按我的预期工作。
使用我的“非工作”代码,我可以通过放置来捕获异常await Initialization
在某处的 try-catch 块中,但我仍然收到一个额外的未处理的异常。
我如何以一种允许我稍后等待我的异步方法(以确保我不会处理对象的不一致状态)并且仍然能够取消该长时间运行的任务(这当然会需要返回/设置默认值)?