【问题标题】:Asynchronous task in webformsWeb 表单中的异步任务
【发布时间】:2018-08-09 19:09:40
【问题描述】:

我在使用powerbi api调用授权任务时遇到了一些问题。它在Authorize().Wait();抛出AggregateException异常。我也用谷歌搜索了它,但找不到任何解决方案。任何帮助,将不胜感激。这是我的Page_Load 函数代码

protected void Page_Load(object sender, EventArgs e)
{
        credential = new UserCredential(Username, Password);
        Authorize().Wait();
        using (var client = new PowerBIClient(new Uri(ApiUrl), tokenCredentials))
        {
            EmbedToken embedToken = client.Reports.GenerateTokenInGroup(<groupId>, <reportId>, new GenerateTokenRequest(accessLevel: "View", datasetId:<datasetId>));
            Report report = client.Reports.GetReportInGroup(<groupId>,<reportId> );
            System.Diagnostics.Debug.WriteLine("This is embed token");
            System.Diagnostics.Debug.WriteLine(embedToken);
            System.Diagnostics.Debug.WriteLine("this is embed url");
            System.Diagnostics.Debug.WriteLine(report.EmbedUrl);


        }

}

在这个函数中,我提取嵌入令牌并嵌入 url 并在输出窗口中打印,下面是授权函数代码

private static Task Authorize()
{
    return Task.Run(async () =>
    {
        authenticationResult = null;
        tokenCredentials = null;
        var authenticationContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize/");

        authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, clientId, credential);

        if (authenticationResult != null)
        {
            tokenCredentials = new TokenCredentials(authenticationResult.AccessToken, "Bearer");
        }
    });
}

【问题讨论】:

  • 请检查AggregateException 的内部异常并确保发布所有信息。为什么在这种情况下使用Task.Run?因为AcquireTokenAsync 已经返回Task,所以不需要它。此外,您应该删除阻塞调用并将签名更改为 protected async void Page_Load(object sender, EventArgs e)

标签: c# azure async-await powerbi


【解决方案1】:

AggregateException 中存在最初抛出的异常。当抛出 1 个或多个异常时,AggregateException 就像 Task 的包装器(在链接任务时可能更多,例如 ContinueWith)。

https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.exception(v=vs.110).aspx

如果您真的想要抛出的异常,请使用GetAwaiter().GetResult() 而不是Wait()

但是,在使用 Web 表单时,请避免在 Task 上使用 Wait()。在页面生命周期挂钩中让 Webforms 运行异步任务的最佳方法是使用 PageAsyncTask 作为异步方法的包装器,并使用 RegisterAsyncTask(PageAsyncTask task) 注册它。另外,请确保您已在页面本身上指定了 Async="true" 属性。

像这样包装 Authorize 方法:RegisterAsyncTask(new PageAsyncTask(Authorize));

一个完整的例子可以在这里找到: https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

不要使用async void Page_Load,因为这会导致意外行为,只有在 Windows 窗体中这才有效,因为有一个 UI 线程。请参阅此博客文章以供参考: https://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx

Authorize 方法可以通过删除 Task.Run 进行优化,因为您已经可以拥有一个异步方法。

private static async Task Authorize()
{
    authenticationResult = null;
    tokenCredentials = null;
    var authenticationContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize/");

    authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, clientId, credential);

    if (authenticationResult != null)
    {
        tokenCredentials = new TokenCredentials(authenticationResult.AccessToken, "Bearer");
    }
}

请注意方法中的“async”关键字,并且 Task.Run 已被删除。

【讨论】:

  • 感谢您的回答,但现在我在 var client = new PowerBIClient(new Uri(ApiUrl), tokenCredentials) 这一行得到了 AurgumentNullException。
  • authenticationResult 是空的吗?根据Authorize 方法,您有一个包装在tokenCredentials 上的if 语句。 ApiUrl 定义了吗?
  • 是的ApiUrl 已定义,但我不知道由于某种原因它不会进入Authorize() 任务,因为我通过在`Task Authorize()` 函数中将值打印到输出窗口来检查它
  • 当使用断点(或打印到输出)时,它应该运行良好。我这里有一个例子:protected void Page_Load(object sender, EventArgs e) { Authorize().GetAwaiter().GetResult(); } private static Task Authorize() { return Task.Run(async () => { await Task.Delay(100); }); }
  • 我忘记在 Aspx 页面中添加Async="true",这就是它没有调用异步方法的原因
猜你喜欢
  • 2013-11-14
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多