C# 在同步方法中使用异步图形API

C# 在同步方法中使用异步图形API,c#,vb.net,multithreading,asynchronous,async-await,C#,Vb.net,Multithreading,Asynchronous,Async Await,我对这个不同步的世界还不熟悉,所以请接受我的知识 目前,;我们正在致力于实现Graph API以获取邮件文件夹、消息等交换数据。由于Graph API遵循APM(异步编程模型),我们遇到了“通过Asyc同步”的情况 _GraphServiceClient.Me.MailFolders.Request.GetAsync() 背景 List<MailFolder> mFolders = AsyncHelper.RunSync(async () => await GraphServ

我对这个不同步的世界还不熟悉,所以请接受我的知识

目前,;我们正在致力于实现Graph API以获取邮件文件夹、消息等交换数据。由于Graph API遵循APM(异步编程模型),我们遇到了“通过Asyc同步”的情况

_GraphServiceClient.Me.MailFolders.Request.GetAsync()
背景

List<MailFolder> mFolders = AsyncHelper.RunSync(async () => await GraphService.GetMailFolders(_GraphServiceClient));
让我把情况说出来,;邮件发送和不同邮件的相关代码位于我们的根类库中,它具有同步方法

这些方法将从同一库的不同类(即执行工作流步骤将发送邮件等)和ASP.NET Web应用程序、Windows窗体应用程序、控制台应用程序调用。现在,我们不能将邮件发送类的方法标记为Async,因为异步病毒会传播,并且我们不能使所有调用方都是异步的。将有大量代码需要重构

从过去几天开始,;我一直在阅读以下相关的洞察全文(Stephen Toub&Stephen Cleary)和一些这样的帖子

所以,在阅读了上面的相关文章和网上的其他文章之后;我认为下面的方法我需要使用。 介绍Asynchelper包装器,它在线程池的另一个线程(使用Task.Run)中执行异步方法,并阻止当前线程

图形服务类:使所有图形通信并获得相关结果

static class GraphService
{
    public async static Task<List<MailFolder>> GetMailFolders(GraphServiceClient graphClient)
    {
        UserMailFoldersCollectionPage mFolders = await graphClient.Me.MailFolders.Request.GetAsync();
        return mFolders.CurrentPage;
    }
}
静态类图服务
{
公共异步静态任务GetMailFolders(GraphServiceClient graphClient)
{
UserMailFoldersCollectionPage mFolders=await graphClient.Me.MailFolders.Request.GetAsync();
返回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();
    }
}
使用系统;
使用System.Threading.Tasks;
内部静态类AsyncHelper
{
//Private ReadOnly _mytaskfactoryas TaskFactory=New TaskFactory(CancellationToken.None,TaskCreationOptions.None,TaskContinuationOptions.None,TaskScheduler.[默认])
公共静态TResult RunSync(Func Func)
{
//Dim cultureUi=CultureInfo.currentui culture
//Dim culture=CultureInfo.CurrentCulture
//Return\u myTaskFactory.StartNew(函数()
//Thread.CurrentThread.CurrentCulture=区域性
//Thread.CurrentThread.CurrentUICulture=cultureUi
//返回func()
//结束函数)。展开().GetWaiter().GetResult()
返回任务。运行(()=>
{
返回func();
}).ConfigureAwait(false).GetAwaiter().GetResult();
}
公共静态无效运行同步(Func Func)
{
//Dim cultureUi=CultureInfo.currentui culture
//Dim culture=CultureInfo.CurrentCulture
//_myTaskFactory.StartNew(函数()
//Thread.CurrentThread.CurrentCulture=区域性
//Thread.CurrentThread.CurrentUICulture=cultureUi
//返回func()
//结束函数)。展开().GetWaiter().GetResult()
Task.Run(()=>
{
返回func();
}).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
根类库中的用法:

List<MailFolder> mFolders = AsyncHelper.RunSync(async () => await GraphService.GetMailFolders(_GraphServiceClient));
List mFolders=asynchHelper.RunSync(async()=>wait-GraphService.GetMailFolders(_-GraphServiceClient));
你能帮我解决这个建筑设计问题吗

  • 当你没有选择的时候;“异步同步”和“异步同步”的最佳方法是什么
  • 我认为“Async”和“Await”操作符不会导致创建额外的线程;那么异步是如何在同一线程中发生的。从技术上讲“Async”和“Await”如何在不创建新线程的情况下实现异步行为?事实上我对Task.Run和Async wait有点困惑
  • 在如上所述的GraphService类中;它只返回当前页面数据。我们需要获取所有邮件文件夹,所以我想我们需要执行循环,然后再次执行相同的requurest来获取所有邮件文件夹,所以我认为;如果需要遵循该方法,我们可能需要遵循该类中的asynchHelper.RunSync选项

提前谢谢。请建议。

对您的一些问题发表评论:

当你没有选择的时候;哪种方法是最好的选择 “异步同步”和“异步同步”


如果您想从异步转到同步,则需要等待,从而阻塞线程。我认为您的AsyncHelper是可以的,但我看不出您为什么要创建和等待其他任务。只需等待Func给出的任务。和
ConfigureAwait(false)
仅在与
await
一起使用时有效。见下文

我认为“Async”和“Await”操作符不会导致额外的线程 被创造;那么异步是如何在同一线程中发生的。 从技术上讲“异步”和“等待”如何通过 我们正在创建一个新线程吗?事实上我有点困惑 Task.Run&异步等待

我相信文档中说,创建新线程是没有道理的。它可能会创建新线程。它还取决于
上下文

在如上所述的GraphService类中;它只返回当前页面 数据。我们需要获取所有邮件文件夹,这样我想我们需要 执行循环,然后再次执行相同的Requirest以获取所有邮件 我想是这样的;我们可能需要遵循Asynchelper.RunSync选项 在那门课上,如果我们需要遵循这种方法

请注意,async/await并不意味着多任务。您可以看看TPL(任务并行库)

AsyncHelper:

internal static class AsyncHelper
{
    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        return func().GetAwaiter().GetResult();
    }

    public static void RunSync(Func<Task> func)
    {
        func().Wait();
    }
}
内部静态类AsyncHelper
{
公共静态TResult RunSync(Func Func)
{
return func().GetAwaiter().GetResult();
}
公共静态无效运行同步(Func Func)
{
func().Wait();
}
}

对一些问题的评论: