微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我目前正在尝试将相当数量的现有同步代码移植到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的精神;但我希望这些方法通常只能在后台线程上调用;我写这篇文章的目的是让我的代码跨平台兼容 – 包括那些尚未支持await-async的平台和/或尚未准备好跳转的开发人员.

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

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

解决方法

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

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

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

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

原文地址:https://www.jb51.cc/java/128784.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐