我必须使用一个API来强制实现其回调接口的类作为身份验证方法的参数。
public class CallBack : ICallBack
{
public object Response;
public void OnSuccess(object response)
{
Response = response;
}
public void OnException(Exception ex) { }
}
身份验证呼叫
public async Task<bool> LoginAsync(string username, string password)
{
CallBack callback = new CallBack();
await Task.Factory.StartNew(
() => userService.Authenticate(username, password, callback),
TaskCreationOptions.AttachedToParent);
return callback.Response is User ? true : false;
}
问题是LoginAsync
在调用回调之前完成。我希望通过使用Authenticate
启动TaskCreationOptions.AttachedToParent
调用,它会传播到Authenticate
中启动的任何子任务,但事实并非如此。
答案 0 :(得分:4)
您应该使用TaskCompletionSource对象将基于回调的异步方法包装到一个等待的任务中。
我假设你的ICallBack是这样的:
public interface ICallBack
{
void OnSuccess(object response);
void OnException(Exception ex);
}
所以你可以像这样实现LoginAsync:
public async Task<bool> LoginAsync(string username, string password)
{
var tcs = new TaskCompletionSource<object>();
ICallBack callback = new CallBackAsync(tcs);
userService.Authenticate(username, password, callback);
var result = await tcs.Task;
return result is User ? true : false;
}
public class CallBackAsync : ICallBack
{
private TaskCompletionSource<object> _tcs;
public CallBackAsync(TaskCompletionSource<object> tcs)
{
_tcs = tcs;
}
public void OnSuccess(object response)
{
_tcs.TrySetResult(response);
}
public void OnException(Exception ex) {
_tcs.TrySetException(ex);
}
}
为了快速解释,当您使用Task.Factory.StartNew()时,在lambda表达式的末尾引发任务的完成。但在你的情况下,这发生在CallBack.OnSuccess调用之前。所以结果没有设定。
TaskCompletionSource类允许您完全控制何时必须完成任务。