等待异步方法返回
本文关键字:返回 异步方法 等待 | 更新日期: 2023-09-27 18:16:48
我有一个类:
public class User
{
public string id, name, email, image;
public User (IFBGraphUser user)
{
id = user.GetId ();
name = user.GetName ();
GetEmail ();
}
private void GetEmail()
{
FBRequestConnection.StartWithGraphPath ("/me", null, "GET", ConnectionReturn);
}
private void ConnectionReturn(FBRequestConnection connection, NSObject result, NSError error)
{
var me = (FBGraphObject)result;
Console.WriteLine("this is a test");
this.email = me["email"].ToString();
}
}
使用async方法:StartWithGraphPath
当构造函数被调用时,我想在GetEmail
返回之前等待StartWithGraphPath
完成。
我怎样才能做到这一点?
StartWithGraphPath
不返回IAsyncResult
,所以我不能使用AsyncWaitHandle
。
编辑
当代码被调用时:
User u = new User(user);
Console.WriteLine("hello");
应用程序输出:
hello
this is a test
这就是让我相信StartWithGraphPath
被称为async的原因。还有别的解释吗?
奇怪的是还有一个方法叫做StartWithGraphPathAsync所以我用的这个不是通过演绎而同步的吗?它在调试器中有同步的感觉,但在简单运行应用程序时就没有了
我不会等待它在构造函数中完成。使异步对消费代码可见(以更友好的形式),并且它可以选择何时或是否实际执行等待电子邮件值:
public class User
{
public string id, name, image;
public User (IFBGraphUser user)
{
id = user.GetId ();
name = user.GetName ();
GetEmail ();
}
public Task<string> Email {
get{
return emailTask.Task;
}
}
private TaskCompletionSource<string> emailTask =
new TaskCompletionSource<string>();
private void GetEmail()
{
FBRequestConnection.StartWithGraphPath ("/me", null, "GET", ConnectionReturn);
}
private void ConnectionReturn(FBRequestConnection connection, NSObject result, NSError error)
{
var me = (FBGraphObject)result;
Console.WriteLine("this is a test");
emailTask.SetResult(me["email"].ToString());
}
}
一个快速的解决方案是使用ManualResetEvent
或ManualResetEventSlim
,在构造函数中等待它,并在回调方法中设置它:
private readonly ManualResetEventSlim myEvent;
public User(IFBGraphUser user)
{
myEvent = new ManualResetEventSlim();
id = user.GetId();
name = user.GetName();
GetEmail();
myEvent.Wait();
}
private void ConnectionReturn(FBRequestConnection connection, NSObject result, NSError error)
{
var me = (FBGraphObject)result;
Console.WriteLine("this is a test");
this.email = me["email"].ToString();
myEvent.Set();
}
请注意这个解决方案只有在StartWithGraphPath方法没有使用被用来调用它来调用回调的线程时才有效。如果是这样——例如,靠近用户界面的类经常会在UI线程上执行回调——那么就会发生死锁。(感谢@L。B)指出这一点
如果你可以修改你的类设计,我建议从构造函数中删除昂贵的调用。构造一个对象通常应该是便宜的,并且在其中使用异步方法意味着它可能需要一些时间。