C# 获取Graph API的访问令牌在控制台应用程序中有效,但在窗体应用程序中挂起

C# 获取Graph API的访问令牌在控制台应用程序中有效,但在窗体应用程序中挂起,c#,winforms,asynchronous,microsoft-graph-api,C#,Winforms,Asynchronous,Microsoft Graph Api,我可以使用控制台应用程序成功获取用于对Graph API进行身份验证的访问令牌,但是,当尝试使用Windows forms应用程序实现相同代码时,它挂起在以下行:result=wait app.AcquireTokenForClient(scope.ExecuteAsync() 我尝试了与以下代码不同的方法,例如使用Microsoft Graph SDK,它再次在控制台应用程序中工作,导致访问代码位于result.AccessToken中,这样我就可以调用Graph API,但是result=w

我可以使用控制台应用程序成功获取用于对Graph API进行身份验证的访问令牌,但是,当尝试使用Windows forms应用程序实现相同代码时,它挂起在以下行:
result=wait app.AcquireTokenForClient(scope.ExecuteAsync()

我尝试了与以下代码不同的方法,例如使用Microsoft Graph SDK,它再次在控制台应用程序中工作,导致访问代码位于result.AccessToken中,这样我就可以调用Graph API,但是
result=wait app.AcquireTokenForClient(scope.ExecuteAsync()在表单应用程序中使用时不完整

using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace SimpleOnePagerConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            RunAsync().GetAwaiter().GetResult();
        }
        private static async Task RunAsync()
        {

            var clientId = "76a824c0-4dce-xxxx-xxxx-xxxxxxxxxxxx";
            var tenantId = "xxxxxxxxxxxx.onmicrosoft.com";
            var clientSecret = "B-0PWoQHPK1_-xxxxxxxxxxxxxxxxxxxx";
            var scope = new string[] { "https://graph.microsoft.com/.default" };

            IConfidentialClientApplication app;


            app = ConfidentialClientApplicationBuilder.Create(clientId)
                .WithClientSecret(clientSecret)
                .WithTenantId(tenantId)
                .Build();


            AuthenticationResult result = null;
            try
            {
                result = await app.AcquireTokenForClient(scope)
                    .ExecuteAsync();
                
            }
            
        }
    }
}
我完全预料到,在使用表单应用程序时,在异步/等待方面我缺少了一些东西,我感谢您提供的任何帮助

编辑:下面是挂起在我前面提到的“ExecuteAsync()”上的一些代码

using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Identity.Client;

namespace SimpleFormsApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void getToken_Click(object sender, EventArgs e)
        {
            RunAsync().GetAwaiter().GetResult();
            
        }
        public static async Task RunAsync()
        {

            var clientId = "76a824c0-4dce-xxxx-xxxx-xxxxxxxxxxxx";
            var tenantId = "xxxxxxxxxxxx.onmicrosoft.com";
            var clientSecret = "B-0PWoQHPK1_-xxxxxxxxxxxxxxxxxxxx";
            var scope = new string[] { "https://graph.microsoft.com/.default" };

            IConfidentialClientApplication app;


            app = ConfidentialClientApplicationBuilder.Create(clientId)
                .WithClientSecret(clientSecret)
                .WithTenantId(tenantId)
                .Build();


            AuthenticationResult result = null;
            
            try
            {
                MessageBox.Show("Getting Token");
                result = await app.AcquireTokenForClient(scope)
                    .ExecuteAsync();
                MessageBox.Show(result.AccessToken);

            }
            catch
            {
                MessageBox.Show("Ended up in catch block");
            }


        }
    }
}
正如在的MSDN文章-或他的文章中所述,您正在导致代码死锁。你可以阅读他的博客和我上面链接的MSDN文章

事件处理程序是
async/await
中规则的1个例外,您可以将方法
getToken\u Click(object sender,EventArgs e)
标记为
async void
,因此更改为该方法将消除死锁问题:

private async void getToken_Click(object sender, EventArgs e)
{
    await RunAsync();
}
此外,如果要从方法返回令牌,可能需要更改为返回
任务
,其中
T
是令牌的对象类型:

public static async Task<T> RunAsync()
公共静态异步任务RunAsync()

不要发布控制台应用程序的工作代码,而是发布表单应用程序不工作的代码。使用我组装的快速表单应用程序修改我的帖子。非常感谢,伙计,这非常有效。我一定会去读你提到的两篇文章。我觉得我现在可以修改我真正的应用程序,开始使用表单应用程序进行图形调用。再次感谢你。@Ashdmckenzie没问题。很高兴我能帮忙。我一直在努力解决
async/await
,Stephen很友好地向我解释了其中的一些问题。只是想把钱预付。快乐编码。