我有一个班级:
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();
}
}
使用异步方法:StartWithGraphPath
当调用构造函数时,我想在StartWithGraphPath
返回之前等待GetEmail
完成。
我该如何做到这一点?
StartWithGraphPath
未返回IAsyncResult
,因此我无法使用AsyncWaitHandle
。
修改
调用代码时:
User u = new User(user);
Console.WriteLine("hello");
我的应用程序输出:
hello
this is a test
这让我相信StartWithGraphPath
被称为异步。还有其他解释吗?
奇怪的是还有一种名为StartWithGraphPathAsync的方法 所以我不会通过演绎来同步这个吗? 它在调试器中具有同步感,但在简单地运行应用程序时却没有
答案 0 :(得分:1)
我不会等待它在构造函数中完成。使异步可见(以更友好的形式)到消费代码,它可以选择何时或是否实际执行等待电子邮件值:
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());
}
}
答案 1 :(得分:-1)
快速解决方案是使用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指出这一点)
如果您可以修改类设计,我建议从构造函数中删除昂贵的调用。构造一个对象通常应该很便宜,并且在其中使用异步方法表明它可能需要一些时间。