gpt4 book ai didi

.net - 使用 Task.Wait() 代码包装 Async/Await IAsyncOperations 有哪些风险?

转载 作者:行者123 更新时间:2023-12-02 13:26:47 27 4
gpt4 key购买 nike

我目前正在尝试将大量现有同步代码移植到 WinRT。

作为其中的一部分,我遇到了现有代码的问题,期望某些操作是同步的 - 例如用于文件 I/O

为了使现有代码能够与 WinRT 中的 IAsyncOperation 样式 API 配合使用,我使用了一种用扩展方法包装 IAsyncOperation 的技术,例如:

namespace Cirrious.MvvmCross.Plugins.File.WinRT
{
public static class WinRTExtensionMethods
{
public static TResult Await<TResult>(this IAsyncOperation<TResult> operation)
{
var task = operation.AsTask();
task.Wait();
if (task.Exception != null)
{
// TODO - is this correct?
throw task.Exception.InnerException;
}

return task.Result;
}
}
}

来自MvvmCross WinRT ExtensionMethods - 对于 IAsyncAction

使用类似的方法

这些包装器似乎有效 - 它们允许我在同步代码中使用 Async 方法,例如:

    public IEnumerable<string> GetFilesIn(string folderPath)
{
var folder = StorageFolder.GetFolderFromPathAsync(ToFullPath(folderPath)).Await();
var files = folder.GetFilesAsync().Await();
return files.Select(x => x.Name);
}

我知道这并不真正符合 WinRT 的精神;但我希望这些方法通常只能在后台线程上调用;我写这篇文章的目的是使我的代码跨平台兼容 - 包括尚未支持等待异步的平台和/或尚未准备好跳跃的开发人员。

所以...问题是:使用这种类型的代码会带来什么风险?

第二个问题是,有没有更好的方法可以实现文件 I/O 等领域的代码重用?

最佳答案

首先,我认为你的方法可以重写为:

public static TResult Await<TResult>(this IAsyncOperation<TResult> operation)
{
return operation.AsTask().Result;
}

调用Result如果任务尚未完成,将同步等待。它会抛出 AgreggateException如果失败了。我想扔InnerException像你这样做是一个坏主意,因为它会覆盖异常的堆栈跟踪。

关于你的实际问题,我认为使用 Wait() 的最大危险与异步代码一起会出现死锁。如果您启动一些内部使用 await 的操作在 UI 线程上,然后使用 Wait() 等待它在同一个线程上,你会遇到死锁。

如果您不是Wait(),那么这并不重要。在 UI 线程上,但如果可能的话,您仍然应该避免它,因为它违背了整个 async想法。

关于.net - 使用 Task.Wait() 代码包装 Async/Await IAsyncOperations 有哪些风险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10668100/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com