Asynchronous 如何将async/await与期望基于回调的异步活动的SDK一起使用
我正在Xamarin表单中实现本机Android Facebook身份验证,并且正在努力解决Facebook SDK打破我的等待/异步链的问题。SDK需要传递Asynchronous 如何将async/await与期望基于回调的异步活动的SDK一起使用,asynchronous,xamarin,xamarin.android,async-await,task-parallel-library,Asynchronous,Xamarin,Xamarin.android,Async Await,Task Parallel Library,我正在Xamarin表单中实现本机Android Facebook身份验证,并且正在努力解决Facebook SDK打破我的等待/异步链的问题。SDK需要传递IFacebookCallback和GraphRequest.IGraphJSONObjectCallback的实现,它们定义回调以处理结果。我想在请求登录的代码中执行以下操作: public async Task LogInFacebookAsync() { var loginResult = await _facebookMan
IFacebookCallback
和GraphRequest.IGraphJSONObjectCallback
的实现,它们定义回调以处理结果。我想在请求登录的代码中执行以下操作:
public async Task LogInFacebookAsync()
{
var loginResult = await _facebookManager.Login();
// do stuff with result
}
然而,以下是我目前正在做的事情。请求登录的代码:
public void LogInFacebookAsync()
{
_facebookManager.Login(onFacebookLoginComplete);
}
private async Task<string> onFacebookLoginComplete(FacebookUser fbUser, string errorMessage)
{
// do stuff with result
}
是否有任何方法可以包装这些操作,使我“一路异步”
更新:
谢谢你,保罗。我已经按照这些思路思考了,而你真的将解决方案具体化了。我唯一关心的是这个答案是否是线程安全的。如果双击一个按钮或同时进行两个API调用需要登录Facebook,该怎么办?下面是我试图使LoginAsync()
方法更安全的尝试。然而,我不是线程安全方面的专家,我欢迎所有的批评
private TaskCompletionSource<FacebookUser> _loginTcs;
public async Task<FacebookUser> LoginAsync()
{
Task<FacebookUser> loginTask = _loginTcs?.Task;
// Don't want to create a new login request to the Facebook API if one is already being made.
if (loginTask != null && (loginTask.Status == TaskStatus.Running || loginTask.Status == TaskStatus.WaitingForActivation
|| loginTask.Status == TaskStatus.WaitingToRun || loginTask.Status == TaskStatus.WaitingForChildrenToComplete))
{
return await loginTask.ConfigureAwait(false);
}
this._loginTcs = new TaskCompletionSource<FacebookUser>();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_context, new List<string> { "public_profile", "email" });
var user = await this._loginTcs.Task.ConfigureAwait(false);
return user;
}
private TaskCompletionSource\u loginTcs;
公共异步任务LoginAsync()
{
任务登录任务=_loginTcs?.Task;
//如果Facebook API已经发出登录请求,则不希望创建新的登录请求。
如果(loginTask!=null&&(loginTask.Status==TaskStatus.Running | | loginTask.Status==TaskStatus.WaitingForActivation
||loginTask.Status==TaskStatus.WaitingToRun | | loginTask.Status==TaskStatus.WaitingForChildrenToComplete)
{
返回wait loginTask.configurewait(false);
}
这是._loginTcs=new TaskCompletionSource();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_上下文,新列表{“public_profile”,“email”});
var user=wait this.\u loginTcs.Task.configurewait(false);
返回用户;
}
使用一个。不需要其他任何东西
我对该API了解不多(我很惊讶Xamarin没有提供一个惯用的.NET版本),但大致上,您需要做的是:
向类中添加任务完成源,而不是\u onLoginComplete
委托:
// public Func<FacebookUser, string, Task> _onLoginComplete;
private TaskCompletionSource<FacebookUser> completion;
更改OnError
方法以完成有错误的任务:
public void OnError(FacebookException error)
{
this.completion.TrySetException(error);
}
更改您的OnCompleted
以设置任务结果:
public void OnCompleted(JSONObject p0, GraphResponse p1)
{
// extract user
this.completion.TrySetResult(fbUser);
}
更改登录方法以创建任务完成源并返回任务完成源的任务:
public async Task<FacebookUser> LoginAsync()
{
this.completion = new TaskCompletionSource<FacebookUser>();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_context, new List<string> { "public_profile", "email" });
await this.completion.Task;
}
public异步任务LoginAsync()
{
this.completion=new TaskCompletionSource();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_上下文,新列表{“public_profile”,“email”});
等待这项任务的完成;
}
使用一个。不需要其他任何东西
我对该API了解不多(我很惊讶Xamarin没有提供一个惯用的.NET版本),但大致上,您需要做的是:
向类中添加任务完成源,而不是\u onLoginComplete
委托:
// public Func<FacebookUser, string, Task> _onLoginComplete;
private TaskCompletionSource<FacebookUser> completion;
更改OnError
方法以完成有错误的任务:
public void OnError(FacebookException error)
{
this.completion.TrySetException(error);
}
更改您的OnCompleted
以设置任务结果:
public void OnCompleted(JSONObject p0, GraphResponse p1)
{
// extract user
this.completion.TrySetResult(fbUser);
}
更改登录方法以创建任务完成源并返回任务完成源的任务:
public async Task<FacebookUser> LoginAsync()
{
this.completion = new TaskCompletionSource<FacebookUser>();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_context, new List<string> { "public_profile", "email" });
await this.completion.Task;
}
public异步任务LoginAsync()
{
this.completion=new TaskCompletionSource();
LoginManager.Instance.SetLoginBehavior(LoginBehavior.NativeWithFallback);
LoginManager.Instance.LogInWithReadPermissions(_上下文,新列表{“public_profile”,“email”});
等待这项任务的完成;
}
您可以设置自动resetEvent
并使用等待的任务执行waitone。运行以避免阻塞主线程,类似于:您可以设置自动resetEvent
并使用等待的任务执行waitone。运行以避免阻塞主线程,比如:再详细说明一下,谢谢,这是一个很好的答案!你介意看一下我问题的编辑吗?我试图将实现增强为线程安全,但我不是线程安全方面的专家。再详细说明一下,谢谢,这是一个极好的答案!你介意看一下我问题的编辑吗?我试图增强实现的线程安全性,但我不是线程安全方面的专家。