Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不使用异步事件时继续_C#_Events_Asynchronous - Fatal编程技术网

C# 不使用异步事件时继续

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

我已经修改了一些代码,这些代码从v2.0异步结构异步执行事件到TPL。这一切似乎都很好,但我有一个奇怪的地方,我不明白

这是异步处理触发事件的类:

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()
(在执行时,因为您可以