2016-04-16 64 views
3

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

Bacause我写一个处理程序,我可以设法得到这样的异步方法GetString的结果: 私人无效Mr_MyEvent(对象发件人,MyEventArgs e) {s} s = GetString()。 e.Change = true; }但如果其他人写一个处理程序呢?如何等待事件处理程序在“OnMyEvent”方法中完成? – vpetrovic

回答

2

我在我的博客上讨论a variety of approaches for asynchronous events。我建议延期的做法,您可以实现使用DeferralManagerIDeferralSource类型从我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; 
    } 
    } 
} 
+0

用这种方法干得好,我会尽力在我的项目中实现这一点。所以我们必须意识到“邪恶”异步事件处理程序并自己处理这些情况。 – vpetrovic