【问题标题】:Async event handler callback through event arguments通过事件参数的异步事件处理程序回调
【发布时间】:2016-04-16 07:58:38
【问题描述】:

当我需要收集已通过包含异步调用的事件 hadnler 更改的事件参数数据时,我遇到了问题。正如您在下面的代码中看到的,MessageReceiver 引发事件并从属性“更改”收集数据,并继续处理。问题是事件处理程序是异步的,因为它使用“await”调用 asny 方法。在方法 OnMyEvent 中,代码在调用处理程序后立即继续,它不等待处理程序完成,因此没有设置“更改”属性......如何让事情更加“同步”?

public class MyEventArgs:EventArgs
{
    public bool Change { get; set; }
}

public delegate void MyEventHandler(object sender, MyEventArgs e);

public class MessageReceiver
{
    public event MyEventHandler MyEvent;

    public void RaiseEvent()
    {
        OnMyEvent();
    }

    protected void OnMyEvent()
    {
        MyEventArgs e = new MyEventArgs();
        if (MyEvent != null)
            MyEvent(this, e);
        if (e.Change)
            Console.WriteLine("Change occured");
    }
}
public class Form
{
    MessageReceiver mr;
    public Form(MessageReceiver MR)
    {
        mr = MR;
        mr.MyEvent += Mr_MyEvent;
    }

    private async void Mr_MyEvent(object sender, MyEventArgs e)
    {
        string s = await GetString();
        e.Change = true;
    }

    public async Task<string> GetString()
    {
        return await Task.Factory.StartNew(() =>
        {
            return Guid.NewGuid().ToString();
        }
            );
    }
}
public class Program
{
    static void Main(string[] args)
    {
        MessageReceiver mr = new MessageReceiver();
        Form frm = new Form(mr);
        mr.RaiseEvent();
    }
}

【问题讨论】:

  • 因为我正在编写一个处理程序,我可以设法从异步方法 GetString 获取结果,如下所示: private void Mr_MyEvent(object sender, MyEventArgs e) { string s = GetString().Result; e.改变=真;但是如果其他人编写处理程序怎么办?如何在方法“OnMyEvent”中等待事件处理程序完成?

标签: c# events asynchronous


【解决方案1】:

我在我的博客上讨论a variety of approaches for asynchronous events。我推荐延迟方法,您可以使用我的Nito.AsyncEx.Coordination library 中的DeferralManagerIDeferralSource 类型来实现它:

public class MyEventArgs: EventArgs, IDeferralSource
{
  private readonly DeferralManager _deferralManager;
  public MyEventArgs(DeferralManager deferralManager)
  {
    _deferralManager = deferralManager;
  }
  public bool Change { get; set; }
  public IDisposable GetDeferral() { return _deferralManager.GetDeferral(); }
}

public class MessageReceiver
{
  protected async Task OnMyEventAsync()
  {
    if (MyEvent != null)
    {
      DeferralManager deferralManager = new DeferralManager();
      MyEventArgs e = new MyEventArgs(deferralManager);
      MyEvent(this, e);
      await deferralManager.WaitForDeferralsAsync();
    }
    if (e.Change)
      Console.WriteLine("Change occured");
  }
}

public class Form
{
  private async void Mr_MyEvent(object sender, MyEventArgs e)
  {
    using (e.GetDeferral())
    {
      string s = await GetString();
      e.Change = true;
    }
  }
}

【讨论】:

  • 很好地使用了这种方法,我将尝试在我的项目中实现它。所以我们必须意识到“邪恶”的异步事件处理程序并自己处理这些情况。
猜你喜欢
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多