[英]run async code from non async method
我正在嘗試從Azure AD獲取訪問令牌,並且異步調用永遠不會完成。 我不確定自己在做什么錯,也許有人可以指出我正確的方向。 這是代碼:
private static void GetAccessTokenNonAsync()
{
Func<System.Threading.Tasks.Task> task = async () => { await GetAccessToken().ConfigureAwait(false); };
task().Wait();
}
private static async Task<AuthenticationResult> GetAccessToken()
{
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
string source = ConfigurationManager.AppSettings["ExchangeOnlineId"];
var authContext = new AuthenticationContext(aadInstance, false);
var credentials = new ClientCredential(clientId, clientSecret);
var appRedirectUrl = HttpContext.Current.GetOwinContext().Request.Scheme + "://" + HttpContext.Current.GetOwinContext().Request.Host + HttpContext.Current.GetOwinContext().Request.PathBase + "/";
var res =
await
authContext.AcquireTokenByAuthorizationCodeAsync(
((ClaimsIdentity)HttpContext.Current.User.Identity).FindFirst("AuthenticationCode").Value,
new Uri(appRedirectUrl), credentials, source).ConfigureAwait(false);
Current.AccessToken = res.AccessToken;
return res;
}
private static string AccessToken
{
get
{
return HttpContext.Current.Session["AccessToken"].ToString();
}
set { HttpContext.Current.Session["AccessToken"] = value; }
}
在我的主要方法中,我調用GetAccessTokenNonAsync()
您正在陷入僵局,因為您阻塞了異步代碼 。 我在博客上描述了詳細信息。
理想情況下,您不應在任何新代碼中使用HttpContext.Current
。 長期以來,它一直被認為是不良實踐,並且已在ASP.NET Core中完全刪除(並且不會再出現)。
看起來您想要做的是將令牌存儲在會話狀態中,並在必要時(異步)創建它。 適當的方法是使訪問器異步:
public static async Task<string> GetAccessTokenAsync()
{
var result = HttpContext.Current.Session["AccessToken"] as string;
if (result != null)
return result;
...
var res = await authContext.AcquireTokenByAuthorizationCodeAsync(...);
result = res.AccessToken.ToString();
HttpContext.Current.Session["AccessToken"] = result;
return result;
}
您沒有正確使用async關鍵字。 這樣的事情應該起作用:
public static void GetAccessTokenNonAsync()
{
// Call the async method and get the resulting task.
Task<AuthenticationResult> accessTokenTask = GetAccessToken();
// Wait for the task to finish.
accessTokenTask.Wait();
}
private async static Task<AuthenticationResult> GetAccessToken()
{
return await Task.Factory.StartNew<AuthenticationResult>
(
() =>
{
// Insert code here.
return new AuthenticationResult();
}
);
}
最終起作用的代碼是這樣的:
private static void GetAccessTokenNonAsync()
{
var userId = ((ClaimsIdentity)HttpContext.Current.User.Identity).FindFirst("UserId").Value;
var task = System.Threading.Tasks.Task.Run(async () =>
{
return await GetAccessToken( userId);
});
task.Wait();
Current.AccessToken = task.Result.AccessToken;
Current.AccessTokenExpiresOn = task.Result.ExpiresOn.ToString();
}
private static async Task<AuthenticationResult> GetAccessToken(string userId)
{
return await System.Threading.Tasks.Task.Factory.StartNew<AuthenticationResult>
(
() =>
{
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
string source = ConfigurationManager.AppSettings["ExchangeOnlineId"];
var authContext = new AuthenticationContext(aadInstance, false);
var credentials = new ClientCredential(clientId, clientSecret);
var res =
authContext.AcquireTokenSilentAsync(source, credentials,
new UserIdentifier(userId, UserIdentifierType.UniqueId)).Result;
return res;
}
);
}
由於您的異步代碼返回了某些內容(使用任務簽名),因此如果您針對最新的.net框架,請嘗試執行以下操作:
private static void GetAccessTokenNonAsync()
{
var result = GetAccessToken().ConfigureAwait(false).Result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.