C# 不使用异步事件时继续
我已经修改了一些代码,这些代码从v2.0异步结构异步执行事件到TPL。这一切似乎都很好,但我有一个奇怪的地方,我不明白 这是异步处理触发事件的类:C# 不使用异步事件时继续,c#,events,asynchronous,C#,Events,Asynchronous,我已经修改了一些代码,这些代码从v2.0异步结构异步执行事件到TPL。这一切似乎都很好,但我有一个奇怪的地方,我不明白 这是异步处理触发事件的类: namespace System { public static class Event { delegate void AsyncFire(Delegate fn, object[] args); private static async Task UnsafeFireAsync(Deleg
namespace System
{
public static class Event
{
delegate void AsyncFire(Delegate fn, object[] args);
private static async Task UnsafeFireAsync(Delegate fn, params object[] args)
{
if (fn == null)
return;
Delegate[] callList = fn.GetInvocationList();
List<Task> taskList = new List<Task>();
AsyncFire asyncFire = InvokeDelegate;
foreach (Delegate sink in callList)
{
var tcs = new TaskCompletionSource<object>();
asyncFire.BeginInvoke(sink, args, AsyncCallback, tcs);
taskList.Add(tcs.Task);
}
await Task.Factory.ContinueWhenAll(taskList.ToArray(), null);
}
static void AsyncCallback(IAsyncResult ar)
{
AsyncFire asyncFire = InvokeDelegate;
var tcs = (TaskCompletionSource<object>)ar.AsyncState;
try
{
asyncFire.EndInvoke(ar);
tcs.SetResult(null);
}
catch(Exception e)
{
tcs.SetException(e);
}
}
static void InvokeDelegate(Delegate fn, object[] args)
{
fn.DynamicInvoke(args);
}
public static async Task FireAsync(EventHandler fn, object sender)
{
await UnsafeFireAsync(fn, sender, EventArgs.Empty);
}
public static async Task FireAsync<T>(EventHandler<T> fn, object sender, T e) where T : EventArgs
{
await UnsafeFireAsync(fn, sender, e);
}
}
}
名称空间系统
{
公共静态类事件
{
委托无效异步火灾(委托fn,对象[]args);
私有静态异步任务UnsafeFireAsync(委托fn,参数对象[]args)
{
如果(fn==null)
回来
委托[]调用列表=fn.GetInvocationList();
List taskList=新列表();
AsyncFire AsyncFire=InvokeDelegate;
foreach(调用列表中的代理接收器)
{
var tcs=new TaskCompletionSource();
BeginInvoke(sink、args、AsyncCallback、tcs);
taskList.Add(tcs.Task);
}
wait Task.Factory.ContinueWhenAll(taskList.ToArray(),null);
}
静态void异步回调(IAsyncResult ar)
{
AsyncFire AsyncFire=InvokeDelegate;
var tcs=(TaskCompletionSource)ar.AsyncState;
尝试
{
asyncFire.EndInvoke(ar);
tcs.SetResult(空);
}
捕获(例外e)
{
tcs.SetException(e);
}
}
静态void InvokeDelegate(委托fn,对象[]args)
{
fn.动力Voke(args);
}
公共静态异步任务FireAsync(EventHandler fn,对象发送方)
{
等待UnsafeFireAsync(fn,发送方,EventArgs.Empty);
}
公共静态异步任务FireAsync(EventHandler fn,object sender,te),其中T:EventArgs
{
等待非安全异步(fn,发送方,e);
}
}
}
然后我有一个类,它提供了一些事件和几个sub来调用它们:
namespace AsyncEventTest
{
class AsyncEvents
{
public event EventHandler Event1;
public event EventHandler Event2;
public event EventHandler Event3;
public event EventHandler Event4;
public event EventHandler<StringEventArgs> Event5;
public void DoProcess()
{
Event1(this, EventArgs.Empty);
Event2(this, EventArgs.Empty);
Event3(this, EventArgs.Empty);
Event4(this, EventArgs.Empty);
Event5(this, new StringEventArgs("Event 5 parameter"));
}
public async Task DoProcessPartialAsync()
{
await Task.Factory.StartNew(DoProcess);
}
public async Task DoProcessFullAsync()
{
Task[] taskList = new Task[5];
taskList[0] = Event.FireAsync(Event1, this);
taskList[1] = Event.FireAsync(Event2, this);
taskList[2] = Event.FireAsync(Event3, this);
taskList[3] = Event.FireAsync(Event4, this);
taskList[4] = Event.FireAsync(Event5, this, new StringEventArgs("Event 5 parameter"));
await Task.Factory.ContinueWhenAll(taskList, null);
}
}
}
命名空间异步事件测试
{
类异步事件
{
公共事件处理程序Event1;
公共事件处理程序Event2;
公共事件处理程序事件3;
公共事件处理程序事件4;
公共事件处理程序事件5;
public void DoProcess()
{
Event1(此,EventArgs.Empty);
Event2(这个,EventArgs.Empty);
Event3(这个,EventArgs.Empty);
Event4(这个,EventArgs.Empty);
Event5(这是新的StringEventArgs(“事件5参数”);
}
公共异步任务DoProcessPartialAsync()
{
等待任务.Factory.StartNew(DoProcess);
}
公共异步任务DoProcessFullAsync()
{
任务[]任务列表=新任务[5];
任务列表[0]=Event.FireAsync(Event1,this);
taskList[1]=Event.FireAsync(Event2,this);
任务列表[2]=Event.FireAsync(Event3,this);
任务列表[3]=Event.FireAsync(Event4,this);
taskList[4]=Event.FireAsync(Event5,this,新的StringEventArgs(“Event5参数”);
wait Task.Factory.ContinueWhenAll(任务列表,空);
}
}
}
然后,我有一个from调用AsyncEvents类并使用其事件:
public partial class Form1 : Form
{
AsyncEvents events = new AsyncEvents();
public Form1()
{
InitializeComponent();
events.Event1 += events_Event1;
events.Event2 += events_Event2;
events.Event3 += events_Event3;
events.Event4 += events_Event4;
events.Event5 += events_Event5;
}
void events_Event5(object sender, StringEventArgs e)
{
System.Threading.Thread.Sleep(4000);
AddToEventList("Event 5 Message: " + e.Message);
}
void events_Event4(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(1000);
AddToEventList("Event 4 Done");
}
void events_Event3(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(2000);
AddToEventList("Event 3 Done");
}
void events_Event2(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(500);
AddToEventList("Event 2 Done");
}
void events_Event1(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(2500);
AddToEventList("Event 1 Done");
}
private void FireAsyncBtn_Click(object sender, EventArgs e)
{
AsyncOutputList.Items.Clear();
events.DoProcessPartialAsync().ContinueWith(t => AddToEventList("DoProcess call done"));
AddToEventList("DoProcess call returned");
}
private void FireFullAsyncBtn_Click(object sender, EventArgs e)
{
AsyncOutputList.Items.Clear();
events.DoProcessFullAsync().ContinueWith(t => AddToEventList("DoProcess call done"));
AddToEventList("DoProcess call returned");
}
private void AddToEventList(string msg)
{
if (InvokeRequired)
{
Invoke((Action<string>)AddToEventList, msg);
return;
}
AsyncOutputList.Items.Add(msg);
}
}
公共部分类表单1:表单
{
AsyncEvents=新的AsyncEvents();
公共表格1()
{
初始化组件();
events.Event1+=events\u Event1;
events.Event2+=events\u Event2;
events.Event3+=事件\u Event3;
events.Event4+=事件\u Event4;
events.Event5+=事件\事件5;
}
void events_Event5(对象发送方,StringEventArgs e)
{
系统线程线程睡眠(4000);
添加事件列表(“事件5消息:+e.Message”);
}
void events\u Event4(对象发送方,事件参数e)
{
系统线程线程睡眠(1000);
添加事件列表(“事件4完成”);
}
void events\u Event3(对象发送方,事件参数e)
{
系统线程线程睡眠(2000);
添加事件列表(“事件3完成”);
}
void events\u Event2(对象发送方,事件参数e)
{
系统.线程.线程.睡眠(500);
添加事件列表(“事件2完成”);
}
void events\u Event1(对象发送方,EventArgs e)
{
系统。线程。线程。睡眠(2500);
添加事件列表(“事件1完成”);
}
私有void FireAsyncBtn_单击(对象发送方,事件参数e)
{
AsyncOutputList.Items.Clear();
events.DoProcessPartialAsync().ContinueWith(t=>AddToEventList(“doProcessCallDone”);
AddToEventList(“返回的DoProcess调用”);
}
私有void FireFullAsyncBtn_单击(对象发送方,事件参数e)
{
AsyncOutputList.Items.Clear();
events.DoProcessFullAsync().ContinueWith(t=>AddToEventList(“doProcessCallDone”);
AddToEventList(“返回的DoProcess调用”);
}
私有void AddToEventList(字符串消息)
{
如果(需要调用)
{
调用((操作)AddToEventList,msg);
回来
}
AsyncOutputList.Items.Add(msg);
}
}
部分异步调用按预期运行:
完全异步调用在事件完成执行之前执行ContinueWith:
我的问题是,为什么?我不明白为什么要提前输出“doProcessDone”行。这不是一个很好的代码示例。看见所以我没有费心去重现这个问题。但是我注意到您正在将
null
作为ContinueWhenAll()
的continuationAction
参数传递,这将引发异常。您可能只是没有注意到异常,因为您自己没有任何try/catch,而表单事件调度正在吞噬它。如果您没有任何实际的继续执行,那么您应该只使用WhenAll()
(在执行时,因为您可以