等待异步方法返回

时间:2014-08-06 08:55:00

标签: c# facebook-graph-api xamarin facebook-ios-sdk

我有一个班级:

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的方法 所以我不会通过演绎来同步这个吗? 它在调试器中具有同步感,但在简单地运行应用程序时却没有

2 个答案:

答案 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)

快速解决方案是使用ManualResetEventManualResetEventSlim,在构造函数中等待它并在回调方法中设置它:

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指出这一点)

如果您可以修改类设计,我建议从构造函数中删除昂贵的调用。构造一个对象通常应该很便宜,并且在其中使用异步方法表明它可能需要一些时间。