当前位置: 首页 > 知识库问答 >
问题:

同步等待异步操作,为什么Wait()在这里冻结程序

束俊材
2023-03-14

尽管我花了几天时间研究了关于基于任务的异步模式(TAP)、async和await的MSDN文章,但我仍然对一些更精细的细节感到有点困惑。

我正在为Windows Store应用程序编写一个记录器,我希望同时支持异步和同步日志记录。异步方法跟随TAP,同步方法应该隐藏所有这些,并且看起来和工作起来像普通方法一样。

这就是异步日志的核心方法:

private async Task WriteToLogAsync(string text)
{
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile file = await folder.CreateFileAsync("log.log",
        CreationCollisionOption.OpenIfExists);
    await FileIO.AppendTextAsync(file, text,
        Windows.Storage.Streams.UnicodeEncoding.Utf8);
}
private void WriteToLog(string text)
{
    Task task = WriteToLogAsync(text);
    task.Wait();
}

这看起来是正确的,但它并不起作用。整个程序永远冻结。

版本2:

嗯..也许任务没有启动?

private void WriteToLog(string text)
{
    Task task = WriteToLogAsync(text);
    task.Start();
    task.Wait();
}
private void WriteToLog(string text)
{
    Task task = WriteToLogAsync(text);
    task.RunSynchronously();
}
private void WriteToLog(string text)
{
    var task = Task.Run(async () => { await WriteToLogAsync(text); });
    task.Wait();
}

这管用。所以,2和3是错误的工具。但是1?1有什么问题,4有什么区别?是什么使1引起冻结?任务对象有问题吗?是否存在不明显的僵局?

共有1个答案

乐正浩宕
2023-03-14

异步方法中的await试图返回UI线程。

由于UI线程正忙于等待整个任务完成,因此您出现了死锁。

将异步调用移动到task.run()解决了这个问题。
因为异步调用现在正在线程池线程上运行,所以它不会尝试返回UI线程,因此所有操作都正常。

 类似资料:
  • 问题内容: 我不确定如何处理这种情况,因为我是iOS开发和Swift的新手。我正在像这样执行数据获取: 我的loadShows()函数解析从加载到UIWebView的网站中获取的大量数据。问题是我在loadShows函数中有一个等待10秒钟左右的计时器。这允许页面中的javascript在开始解析数据之前完全加载。我的问题是完成处理程序在我的loadShows()之前完成。 我想做的是为“ isC

  • 问题内容: 我在创建的Web API中执行以下操作: 通过以下方式通过Jquery Ajax调用完成对此Web服务的调用: 我已经看到一些开发人员以这种方式实现了先前的操作: 不过,得说GetProductsWithHistory()是一个相当长的操作。考虑到我的问题和上下文,使webAPI操作异步将给我带来什么好处? 问题答案: 在您的特定示例中,该操作根本不是异步的,因此您正在执行的操作是异步

  • 我见过一些开发人员以这种方式实现前面的操作: 不过,不得不说,GetProductsWithHistory()是一个相当长的操作。考虑到我的问题和上下文,使webAPI操作异步对我有什么好处?

  • 我试图在react/electron项目中使用async/await,但它不起作用。我想要的是获取docker容器状态列表。但是安慰。日志(列表)返回未定义的。 有人能帮我吗?:)

  • 我最近阅读了有关async/await的文章,我感到困惑的是,我阅读的许多文章/帖子都指出,在使用async await(示例)时不会创建新线程。 我创建了一个简单的控制台应用程序来测试它 以下代码的输出是: 我想知道,如果没有创建其他线程,部分在哪里运行?如果它运行在同一个线程上,难道它不应该因为长的I/O请求而阻塞它吗?或者编译器足够聪明,如果它需要太长的时间,就可以将该操作移到另一个线程上,