我使用DropNet API连接到DropBox。我正在努力解决异步/等待概念。
我有一个方法是调用api GetTokenAsync
。返回类型为void
,并且存在成功和失败操作以进行回调。
public async Task<GetTokenResult> GetAuthorizationUrl()
{
var result = new GetTokenResult();
_dropNetClient.GetTokenAsync(
login =>
{
result.Url = _dropNetClient.BuildAuthorizeUrl(_authorizationCallback.ToString());
result.Success = true;
},
exception =>
{
result.Error = exception.ToDiagnosticString();
result.Success = false;
}
);
return result;
}
问题?我认为将返回类型更改为仅GetTokenResult
可能返回的速度比操作更快,因此我的结果永远不会被设置。我不能await
async方法,因为它返回void。
这是围绕async / await的一个概念,我无法解决这个问题。
答案 0 :(得分:6)
您可能需要考虑使用TaskCompletionSource
:
public Task<GetTokenResult> GetAuthorizationUrl()
{
var tcs = new TaskCompletionSource<GetTokenResult>();
_dropNetClient.GetTokenAsync(
login => tcs.SetResult(new GetTokenResult {
Url = _dropNetClient.BuildAuthorizeUrl(
_authorizationCallback.ToString()),
Success = true
},
exception => tcs.SetResult(new GetTokenResult {
Error = exception.ToDiagnosticString(),
Success = true
});
return tcs.Task;
}
返回的任务仅在GetTokenAsync
操作完成后(通过其中一个回调)完成,您可以从异步方法等待它。
我个人会在失败时使用SetException
代替SetResult
- 所以如果你等待返回的任务,它会在异常上抛出适当的失败,而不是仅仅设置不同的值。它更像是习惯性的.NET。
编辑:然后您可以更改代码以返回Task<string>
:
public Task<string> GetAuthorizationUrl()
{
var tcs = new TaskCompletionSource<string>();
_dropNetClient.GetTokenAsync(
login => tcs.SetResult(_dropNetClient.BuildAuthorizeUrl
_authorizationCallback.ToString()),
exception => tcs.SetException(exception));
return tcs.Task;
}
现在,异常将在任务本身内传播 - 如果await
任务出现故障,则会在该点抛出异常。不需要额外的属性等 - 它更接近你编写相应的同步代码的方式。