等待异步方法返回

本文关键字:返回 异步方法 等待 | 更新日期: 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());
    }
}

一个快速的解决方案是使用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)指出这一点

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