繁体   English   中英

将同步代码转换为异步代码未得到处理 System.OperationCanceledException: 'The operation was canceled.'

[英]Converting sync to async code got unhandled System.OperationCanceledException: 'The operation was canceled.'

我正在尝试将我的同步功能转换为异步。 在我所有的同步功能中,我都有一个取消令牌,用于 function、任务和并行块。 在调用异步 function 之前,我有一个 try/catch 块,但我遇到了一个未处理的异常:

抛出的异常:System.Threading.Tasks.Parallel.dll 中的“System.OperationCanceledException”类型的异常发生在 System.Threading.Tasks.Parallel.dll 中,但未在用户代码中处理该操作已取消。

我的异步 function:

public async Task DecodeAsync(string? fileFullPath, FileDecodeType fileDecodeType, OperationProgress? progress = null) =>
            await Task.Run(() => Decode(fileFullPath, fileDecodeType, progress), progress?.Token ?? default);

我怎么称呼它:

try
        {
            await SlicerFile.DecodeAsync(fileName, fileDecodeType, Progress);
        }
        catch (OperationCanceledException) { } // Do not work!
        catch (Exception exception) // Works for other exceptions
        {
            await this.MessageBoxError(exception.ToString(), "Error opening the file");
        }

cancel catch (OperationCanceledException)永远不会到达,也不会在 cancel 事件中catch (Exception exception) 由于我的尝试最重要,为什么它没有捕获到异常?

但如果我这样做:

public async Task DecodeAsync(string? fileFullPath, FileDecodeType fileDecodeType, OperationProgress? progress = null) =>
            await Task.Run(() => throw new Exception("Test"));

我得到了通用异常的异常捕获(已处理)

另一方面,使用旧代码它正在工作并处理OperationCanceledException

var task = await Task.Factory.StartNew( () =>
        {
            try
            {
                SlicerFile.Decode(fileName, fileDecodeType, Progress);
                return true;
            }
            catch (OperationCanceledException) {} // Works!
            catch (Exception exception) 
            {
                Dispatcher.UIThread.InvokeAsync(async () =>
                    await this.MessageBoxError(exception.ToString(), "Error opening the file"));
            }

            return false;
        });

我究竟做错了什么?

Task.Run 的结果不一定需要在那里等待。 您可以只返回正在运行的任务,然后该方法不再需要等待或异步。

    Task DecodeAsync(string? fileFullPath, FileDecodeType fileDecodeType, OperationProgress? progress = null) => Task.Run(() => 
Decode(fileFullPath, fileDecodeType, progress), progress?.Token ?? default);

并且由于您正在传递一个令牌,您可以监视它以干净地退出解码方法,而不是试图捕获并忽略操作取消的异常。

如果可以的话,如果您使 decode 方法本身异步,那么您的运气会更好。 它已经返回一个任务,所以它可以返回一个任务(或其他)。 您的旧代码也以相同的方式异步,因此我可以看到您的新代码没有任何优势。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM