.net – 使用Task.Wait()代码包装Async / Await IAsyncOperations有什么风险?

前端之家收集整理的这篇文章主要介绍了.net – 使用Task.Wait()代码包装Async / Await IAsyncOperations有什么风险?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我目前正在尝试将相当数量的现有同步代码移植到WinRT.

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

为了使这个现有代码适应WinRT中的IAsyncOperation样式API,我使用了一种使用扩展方法包装IAsyncOperation的技术,如:

  1. namespace CirrIoUs.MvvmCross.Plugins.File.WinRT
  2. {
  3. public static class WinRTExtensionMethods
  4. {
  5. public static TResult Await<TResult>(this IAsyncOperation<TResult> operation)
  6. {
  7. var task = operation.AsTask();
  8. task.Wait();
  9. if (task.Exception != null)
  10. {
  11. // TODO - is this correct?
  12. throw task.Exception.InnerException;
  13. }
  14.  
  15. return task.Result;
  16. }
  17. }
  18. }

MvvmCross WinRT ExtensionMethods开始 – 使用与IAsyncAction类似的方法

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

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

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

所以……问题是:使用这种类型的代码我运行的风险是什么?

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

解决方法

首先,我认为您的方法可以改写为:
  1. public static TResult Await<TResult>(this IAsyncOperation<TResult> operation)
  2. {
  3. return operation.AsTask().Result;
  4. }

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

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

如果你没有在UI线程上等待,那么这并不重要,但如果可能的话,你仍然应该避免它,因为它违背了整个异步的想法.

猜你在找的Java相关文章