无法从ThrowIfCancellationRequested()中捕获异常

时间:2019-01-22 16:36:09

标签: c# xamarin.forms cancellation

欢迎,我有以下代码:

    public static async Task TimedSync (CancellationToken ct)
    {
        try {
            if (ct.IsCancellationRequested)
                ct.ThrowIfCancellationRequested();
            await Task.Run(async () => await UP.Sincronizacao.SyncDB(true));
            Xamarin.Forms.Device.StartTimer(TimeSpan.FromMinutes(1), () => {
                if (ct.IsCancellationRequested)
                    ct.ThrowIfCancellationRequested();
                Task.Run(async () => await UP.Sincronizacao.SyncDB(false));
                return true;
            });
        } catch (OperationCanceledException) {
            await Current.MainPage.DisplayAlert("Got it", "Good", "ok");
        } catch (Exception e) {
            await Current.MainPage.DisplayAlert("Oops", e.Message, "dismiss");
        }
    }

应用程序此时崩溃了,在调试时,我发现ThrowIfCancellationRequested()引发的异常未得到处理。

编辑: 好的,确实发生了一件很奇怪的事情,我删除了第一个if(ct.IsCancellationRequested) ct.ThrowIfCancellationRequested();并遵循了Peter的建议,lambda内的Throw现在引发了异常,我放在上面的try catch块也没有用,但是try catch在lambda之外捕获了异常。这是代码:

    public static async Task TimedSync (CancellationToken ct)
    {
        try {
            await Task.Run(async () => await UP.Sincronizacao.SyncDB(true));
            Xamarin.Forms.Device.StartTimer(TimeSpan.FromMinutes(1), () => {
                try {
                    if (ct.IsCancellationRequested)
                        ct.ThrowIfCancellationRequested();
                    Task.Run(async () => await UP.Sincronizacao.SyncDB(false));
                    return true;
                } catch (OperationCanceledException) {
                    return false;
                }
            });
        } catch (OperationCanceledException) {
            await Current.MainPage.DisplayAlert("Got it", "Good", "ok");
        } catch (Exception e) {
            await Current.MainPage.DisplayAlert("Oops", e.Message, "dismiss");
        }
    }

有点适合我:) 但仍然想了解这里发生的事情

1 个答案:

答案 0 :(得分:1)

您正在传递StartTimer的lambda,当取消发生时,它将抛出CancellationException,但是不一定会在StartTimerTimedSync的范围内触发此异常。

我的猜测是因为我不使用Xamarin,所以运行您的lambda的计时器代码会在单独的任务上看到异常并将其提升为应用程序故障。

如果您在lambda中捕获CancellationException并返回false,则应该具有停止计时器 而不向Xamarin计时器代码传播异常的预期效果。

请注意,直接调用ct.ThrowIfCancellationRequested() 会被捕获在TimedSync内,并击中您的catch块。