【问题标题】:How to integrate WinRT asynchronous tasks into existing synchronous libraries?如何将 WinRT 异步任务集成到现有的同步库中?
【发布时间】:2012-10-11 00:51:48
【问题描述】:

我们有一个长期建立的、非常多平台的代码库,目前正在移植到 WinRT。我们面临的挑战之一是如何处理 WinRT 的异步风格。

例如,我们不确定如何处理 WinRT 的异步文件操作。不出所料,我们代码库的 API 是同步的。一个典型的例子是我们的 File::Open 函数,它尝试打开一个文件并返回成功或失败。我们如何调用 WinRT 函数并保持函数的行为相同?

请注意,不幸的是,我们受到遗留问题的限制:我们不能简单地将 API 更改为异步。

谢谢!

【问题讨论】:

标签: windows asynchronous windows-8 windows-runtime


【解决方案1】:

我假设您希望重新实现该库以支持 WinRT 应用程序,同时不更改 API 的定义以便现有应用程序保持兼容。

我认为,如果在调用异步方法时不包含 await 关键字,则不会执行异步操作,它应该以同步方式执行。但是如果方法返回一个值(根据我的经验),它真的不起作用。

我一直在使用这段代码来同步文件操作:

IAsyncOperation<string> contentAsync = FileIO.ReadTextAsync(file);
contentAsync.AsTask().Wait();
string content = contentAsync.GetResults();

【讨论】:

  • 请注意,在许多情况下,这可能会导致死锁,因为您正在等待的操作可能需要在您正在等待的线程上处理一个事件,从而阻止处理该事件。
  • 那么还有什么其他模式可以使异步调用同步?在我的应用程序中,我想确保在应用程序显示初始屏幕之前阅读此配置信息,因此我必须在某个地方等待此代码完成...@FilipSkakun
  • @MattiasLindberg 使用ConfigureAwait(false); 而不是Wait(),这样它将在后台线程中执行。
【解决方案2】:

如果您想与不支持 async/await 的平台共享您的代码 - 您可能最好为旧平台和新平台使用不同的 API,并使用类似的开关

#if SILVERLIGHT
#elif NETFX_CORE
#elif WPF
#endif

最终,异步 API 很可能会出现在较旧的平台中,您实际上可以将非异步调用包装到任务中,以使它们异步(如果它们不这样做)。强制异步方法同步工作势必会很快反击你。例如,您的 WinRT 应用程序可能会在几秒钟内无响应并被操作系统杀死。或者,您可能会在等待任务完成并阻塞他们尝试完成的线程时遇到死锁。

【讨论】:

  • 可能会更好,但不可能。正如我在帖子中提到的那样,API 已经过时并且几乎一成不变。基于代码库构建的应用程序预计无需或几乎无需更改即可构建和工作。至于响应性,主应用程序代码无论如何都在单独的线程中运行,因此 UI 不受影响。
  • 无法编辑原始评论:基于代码库构建的应用程序预计将在不同平台上构建和工作,而无需或几乎没有任何更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多