我对C#中的任务(Tasks)还不是很熟悉。我正在尝试按照示例将ARM模板部署到Azure以启动虚拟机:
https://azure.microsoft.com/zh-cn/documentation/articles/arm-template-deployment/这里给出的第一个操作之一是通过调用Active Directory来获取授权令牌。链接中给出的代码使用的是AcquireToken api,但该api似乎已被弃用,目前只能找到AcquireTokenAsync。因此,我修改了代码创建了一个任务,并等待其完成:
private static string GetAuthorizationHeader()
{
ClientCredential cc = new ClientCredential("{application-id}", "{password}");
var context = new AuthenticationContext("https://login.windows.net/{tenant-id}");
Task<AuthenticationResult> acquireTokenTask = context.AcquireTokenAsync("https://management.azure.com/", cc);
Task.WhenAll(acquireTokenTask);
AuthenticationResult result = acquireTokenTask.Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
我原本以为Task.WhenAll会一直阻塞,直到acquireTokenTask的状态变为“RanToCompletion”。但是即使状态是“WaitingForActivation”,WhenAll也不会阻塞,控制权转移到下一个语句,尝试获取acquireTokenTask.Result。这导致了一个异常,其中详细说明有一个发送请求的错误。
问题: 1. 请求发送时是否存在错误,导致状态没有更改为“RanToCompletion”?我认为这不是问题,因为在10次运行中有2-3次成功并且我能够得到结果。 2. 我认为Task.WhenAll会阻塞线程,直到它运行完成。这不是真的吗?如果是,我想知道控制权是如何传递到下一个语句的。 3. 如何解决此问题并在提取结果时每次都获得成功的结果?
Task.WhenAll
会异步地让出,而Task.WaitAll
则会阻塞。但是你为什么要进行阻塞呢?如果您正确地使用await
整个调用链,应该就可以了。 - Yuval ItzchakovTask.Result
代替await
。 - Yuval ItzchakovTask.WhenAll
,而不是等待对AcquireTokenAsync
的调用。如果您可以访问Token
属性,那么这意味着返回的任务已经完成,因此它过早地返回的可能性非常小。 - Yuval Itzchakov