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

Stu*_*art 7 .net async-await c#-5.0 windows-runtime

我目前正在尝试将相当数量的现有同步代码移植到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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

来自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);
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

Stu*_*art 2

终于要来回答这个问题了......

答案是你真的做不到。

即使您尝试使用其他答案中建议的一些更干净的方法,如果您尝试在任何承诺不会阻塞的线程上运行代码,您最终仍然会遇到异常 - 例如,如果您尝试在 UI 线程上运行或者在线程池线程上。

所以...答案是您只需重新构建遗留代码,以便它在某种程度上是异步的!