【问题标题】:c# blocking code in async methodc# 在异步方法中阻塞代码
【发布时间】:2016-03-21 17:55:18
【问题描述】:

我在 Windows 10 (UWP) 应用程序中使用 MvvmCross 和 AsyncEx 库。

在 ViewModel 中,我有一个 INotifyTaskCompletion 属性 (1),它连接到 ViewModel (2) 中的 Async 方法

在(2)中,我调用了一个异步库方法:

  • 检查本地缓存
  • 异步下载数据
  • 将数据添加到缓存中

缓存代码不能异步,因此库方法包含阻塞代码和异步代码。

问。防止阻塞 UI 线程的最佳方法是什么?

我从Stephen Cleary 了解到不要阻塞异步代码,也不要在库方法中使用 Task.Run。所以我必须……。

将缓存调用移动到 (2) 例如

  • 使用 Task.Run(检查缓存)
  • 异步调用库方法
  • 再次使用Task.Run(缓存数据)?

有没有更好的办法?

【问题讨论】:

  • 你有一些代码可以分享吗?
  • 取决于您对“更好”的定义。如果您无法更改缓存代码并想使用 async/await,那么使用 Task.Run() 缓存代码是“正确的”。

标签: c# asynchronous async-await win-universal-app


【解决方案1】:

如果你有完全同步的代码,你不能改变它来让它返回一个等待,并且想要让它异步,那么是的,如果你想使用async/await,你唯一的选择就是使用Task.Run()

类似:

public async Task<T> MyMethod()
{
   T result = await Task.Run(() => CheckCacheOnSyncMethodICantChange());
   if(result != null)
   {
     result = await MyLibraryMethodThatReturnsATask();
     await Task.Run(() => AddToCacheOnSyncMethodICantChange(result));
   }
   return result;
}

应该没问题。

【讨论】:

  • 尽管我的回答是,对于您的具体情况,缓存应该很快(这就是您使用它的原因)...您确定需要使缓存方法异步吗?
  • 我正在使用 SQLite.net 将数据缓存在基于文件的数据库中。因为这项工作不受 CPU 限制,所以我想在不阻塞 UI 线程的情况下进行。我错过了什么吗?
  • @Howard 不,没关系...只要您的库方法比检查和添加到缓存花费更多的时间。我没有使用 SQLite 的经验,但我记得如果你使用的是 SQLite.Net,它有 GetAsyncInsertAsync
  • 我相信 SQLite.net 异步库方法只是在执行一个任务。围绕同步库方法运行,这被描述为一种反模式(某些人)。
  • @Howard 是的,实际上,Task.Factory.StartNew,似乎:github.com/oysteinkrog/SQLite.Net-PCL/blob/master/src/…。嗯,只是没有好的解决方案。如果您的调用代码(即我的回答中的MyMethod)是“校准方法”,而不是“库方法”(应该是,因为您不希望您的库依赖于 sqlite 文件数据库: -) ),然后使用Task.Run 就可以了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多