【发布时间】:2020-05-24 20:03:56
【问题描述】:
我是这个异步世界的新手所以请耐心等待我的知识。
目前;我们正在努力实现 Graph API 以获取邮件文件夹、消息等交换数据。由于 Graph API 遵循 APM(异步编程模型),我们遇到了“Sync over Asyc”的情况。
_GraphServiceClient.Me.MailFolders.Request.GetAsync()
背景
让我把情况说一下;邮件发送和不同的邮件相关代码位于我们的根类库中,它具有同步方法。
这些方法将从同一个库的不同类(即执行工作流步骤将发送邮件等)和 ASP.NET Web 应用程序、Windows 窗体应用程序、控制台应用程序中调用。现在,我们不能将邮件发送类的方法标记为异步,因为异步病毒会传播,我们不能让所有调用者都是异步的。将有大量代码需要重构。
从过去几天开始;我一直在阅读 (Stephen Toub & Stephen Cleary”) 的相关见解全文以及一些 SO 帖子。
- https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development
- https://devblogs.microsoft.com/pfxteam/should-i-expose-synchronous-wrappers-for-asynchronous-methods/
- https://devblogs.microsoft.com/pfxteam/should-i-expose-asynchronous-wrappers-for-synchronous-methods/
- Calling async methods from non-async code
所以,在阅读了上面的相关文章和网络上的其他文章之后;我认为我需要使用以下方法。 引入 Asynchelper 包装器,它在线程池的另一个线程(使用 Task.Run)中执行 Async 方法并阻塞当前线程。
GraphService 类:使所有的图通信并得到相关结果。
static class GraphService
{
public async static Task<List<MailFolder>> GetMailFolders(GraphServiceClient graphClient)
{
UserMailFoldersCollectionPage mFolders = await graphClient.Me.MailFolders.Request.GetAsync();
return mFolders.CurrentPage;
}
}
AsyncHelper
using System;
using System.Threading.Tasks;
internal static class AsyncHelper
{
// Private ReadOnly _myTaskFactory As TaskFactory = New TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.[Default])
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
// Dim cultureUi = CultureInfo.CurrentUICulture
// Dim culture = CultureInfo.CurrentCulture
// Return _myTaskFactory.StartNew(Function()
// Thread.CurrentThread.CurrentCulture = culture
// Thread.CurrentThread.CurrentUICulture = cultureUi
// Return func()
// End Function).Unwrap().GetAwaiter().GetResult()
return Task.Run(() =>
{
return func();
}).ConfigureAwait(false).GetAwaiter().GetResult();
}
public static void RunSync(Func<Task> func)
{
// Dim cultureUi = CultureInfo.CurrentUICulture
// Dim culture = CultureInfo.CurrentCulture
// _myTaskFactory.StartNew(Function()
// Thread.CurrentThread.CurrentCulture = culture
// Thread.CurrentThread.CurrentUICulture = cultureUi
// Return func()
// End Function).Unwrap().GetAwaiter().GetResult()
Task.Run(() =>
{
return func();
}).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
在根类库中的使用:
List<MailFolder> mFolders = AsyncHelper.RunSync(async () => await GraphService.GetMailFolders(_GraphServiceClient));
您能帮我解决这个架构设计问题吗?
- 当您别无选择时;哪个是用于“同步异步”和“异步同步”的最佳方法?
- 我认为“Async”和“Await”运算符不会导致创建额外的线程;那么异步是如何在同一个线程中发生的。技术上; “Async”和“Await”如何在不创建新线程的情况下实现异步行为?实际上;我对 Task.Run 和 Async await 有点困惑。
- 在 GraphService 类中,如上所述;它只返回当前页面数据。我们需要获取所有邮件文件夹,所以我想我们需要执行循环并再次执行相同的请求以获取所有邮件文件夹所以我认为;如果我们需要遵循该方法,我们可能需要遵循该类中的 Asynchelper.RunSync 选项。
提前致谢。请提出建议。
【问题讨论】:
标签: c# vb.net multithreading asynchronous async-await