捕获异步 Lambda 异常

3

我正在使用C#在Windows 8上工作,使用async关键字时,存在一种情况,我似乎无法很好地处理异常。

该情况涉及启动一个async Lambda,并将其发布以在UI线程上运行。
在Lambda代码执行期间发生的异常会在调用线程上重新抛出,而没有能力正确地捕获它们。

例如:此代码块在某个工作线程上执行,并尝试在UI线程上安排工作:

await Window.Current.Dispatcher.RunAsync
        (CoreDispatcherPriority.Normal
         , async () =>
             {
               var result = await CurrentAppSimulator
                                  .RequestProductPurchaseAsync("product, true);
             }
        );

如果lambda表达式中的代码抛出异常,该异常不会被重新提交到此方法的主体。相反,它将由SynchronizationContext或某些类似机制引发,我似乎无法捕获它。
我想要的是从这段代码(调用代码)中捕获此异常的能力。
这是否可能?

为什么要使用Dispatcher进行调用?如果没有其他线程,您不需要这样做;异步调用函数并不会创建新的线程... - daryal
另外,在 RequestProductPurchaseAsync 方法中,你是否使用了 TaskCompletionSource<T>? - daryal
这段代码在工作线程上执行。另外,我没有使用TCS<T>。 - lysergic-acid
你能发布RequestProductPurchaseAsync方法吗? - daryal
这是框架代码,不是我的代码。我正在调用一些Windows API。 - lysergic-acid
1个回答

2

我认为如果可能的话,你不应该这样做。UI线程应该管理后台线程发生的事情,而不是相反。

如果你真的需要这样做,可以使用Task.Factory.StartNew()的重载版本,它允许你指定一个TaskScheduler,再加上Unwrap()将结果为Task<Task>的任务转换为简单的Task

await Task.Factory.StartNew(
    async () =>
        await CurrentAppSimulator.RequestProductPurchaseAsync("product", true),
    CancellationToken.None, TaskCreationOptions.None, scheduler)
    .Unwrap();

或者,你可以使用await await

await await Task.Factory.StartNew(
    async () =>
        await CurrentAppSimulator.RequestProductPurchaseAsync("product", true),
    CancellationToken.None, TaskCreationOptions.None, scheduler);

这意味着您需要通过UI TaskScheduler (您可以在UI线程上调用TaskScheduler.FromCurrentSynchronizationContext()来获取它)将其传递给此方法。

在某些情况下,“代码执行的位置”并不由您决定。在这种情况下,我必须将一些代码发布到UI线程... - lysergic-acid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接