ContinueWhenAll不使用Async Events

时间:2014-12-03 17:39:25

标签: c# events asynchronous

我已经调整了一些代码,这些代码从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);
        }   
    }
}

然后我有一个提供一些事件的类和一些子调用它们:

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

然后我有一个来自它的调用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);
    }
}

部分异步调用按预期运行:

Partial Async Run

完全异步调用虽然在事件执行完毕之前执行ContinueWith:

Fully Async Run

我的问题是,为什么?我不明白为什么&#34; DoProcess Done&#34;线路正在提前输出。

0 个答案:

没有答案