c# - 通过事件参数的异步事件处理程序回调

标签 c# events asynchronous

当我需要收集已通过包含异步调用的事件 hadler 更改的事件参数数据时,我遇到了问题。正如您在下面的代码中看到的,MessageReceiver 引发事件并从属性“Change”收集数据,然后继续处理。问题是事件处理程序是异步的,因为它使用“等待”调用任何方法。在方法 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();
    }
}

最佳答案

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

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;
    }
  }
}

关于c# - 通过事件参数的异步事件处理程序回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36661687/

相关文章:

c# - DbMigration.AlterstoredProcedure( Entity Framework 迁移): How to represent type smallmoney?

jquery - 如何将 jQuery 事件附加到新元素?

javascript - 为什么 await 只适用于 javascript 中的异步函数?

python - 我如何进行异步编程但将其隐藏在 Python 中?

c# - x :FieldModifier ="Private" do and should I worry about it? 是什么

c# - Task.Run(()=> DoWorkAsync()) 和 new Thread(async()=> DoWorkAsync()); 之间的区别

c# - 识别导致回发的控件

javascript 在处理程序中删除事件,

jquery - Dart HTML : add Event Handlers to objects which yet not exists

javascript - 异步调用内的同步调用