Asynchronous windows窗体,异步任务异常捕获

Asynchronous windows窗体,异步任务异常捕获,asynchronous,task,Asynchronous,Task,我有一个表单,两个按钮,一个文本框。按钮1处理TaskException\u单击。 我想做的是理解异步任务/void的区别。但是,检查多个例子,我仍然不理解或使它工作。下面是我的代码。 当我单击taskexception按钮时,未观察到的taskexception没有执行我所期望的。 当我再次单击它时,将执行该事件,但第一次单击除外。但是,UI没有更新,实际上它挂起了。想知道我做错了什么 using System; using System.Collections.Generic; using

我有一个表单,两个按钮,一个文本框。按钮1处理TaskException\u单击。 我想做的是理解异步任务/void的区别。但是,检查多个例子,我仍然不理解或使它工作。下面是我的代码。 当我单击taskexception按钮时,未观察到的taskexception没有执行我所期望的。 当我再次单击它时,将执行该事件,但第一次单击除外。但是,UI没有更新,实际上它挂起了。想知道我做错了什么

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace test
{
    public partial class main : Form
    {
        public main()
        {
            InitializeComponent();
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        }

        void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            //textBox1.Text = "Unobserved Exception caught ";
            e.SetObserved();
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate()
                {
                    //codes to do whatever i wan to do with the GUI
                    //Examples of it would be disposing a flowlayout panel 
                    //and re-adding it back and populating it again to 
                    //show the refreshed values.
                    textBox1.Text = "Unobserved Exception caught " + e.Exception.Message;
                });
            }
            else
            {
                textBox1.Text = "Unobserved Exception caught " + e.Exception.Message;
            }
        }

        private int i = 0;
        // Add async here! You can always add these to events
        private async void TaskException_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
            try
            {
                Task t = TaskThrowAnException();
                textBox1.Text = "done";
                t = null;
                Thread.Sleep(100);
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
            }
            catch (Exception ex)
            {

                textBox1.Text = "Exception caught";
            }
        }


        private async Task TaskThrowAnException()
        {
            //await Task.Delay(1000);
            i++;
            throw new Exception("Task" + i.ToString());
        }

        private async void VoidException_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
            try
            {
                VoidThrowAnException();
                textBox1.Text = "done";
            }
            catch (Exception ex )
            {
                textBox1.Text = "Exception caught";
            }
        }
        private async void  VoidThrowAnException()
        {
            //await Task.Delay(1000);
            throw new Exception("Void");
        }
    }
}
对于TaskException情况,异常存储在任务中,这是返回任务的异步方法的预期行为。如果希望抛出异常,则需要通过等待任务或调用结果或等待任务来观察异常

如果未观察到异常,则在任务完成时应该抛出异常,我唯一能得出的结论是,在调用

Thread.Sleep(100);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
如果添加另一个按钮,并将上面的代码放入按钮处理程序中(例如Clear_Click everything),我也不确定为什么局部变量不是GCed。我认为生成的代码一定有到任务变量的链接,但我找不到任何链接

以下是从Reflector生成的代码:

namespace WindowsFormsApplication1
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

public class Form1 : Form
{
    private IContainer components = null;
    private int i = 0;
    private Button TaskException;
    private TextBox textBox1;
    private Button VoidException;

    public Form1()
    {
        this.InitializeComponent();
        TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(this.TaskScheduler_UnobservedTaskException);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (this.components != null))
        {
            this.components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.textBox1 = new TextBox();
        this.TaskException = new Button();
        this.VoidException = new Button();
        base.SuspendLayout();
        this.textBox1.Location = new Point(13, 13);
        this.textBox1.Multiline = true;
        this.textBox1.Name = "textBox1";
        this.textBox1.Size = new Size(0x20d, 0x13f);
        this.textBox1.TabIndex = 0;
        this.TaskException.Location = new Point(13, 0x16d);
        this.TaskException.Name = "TaskException";
        this.TaskException.Size = new Size(0x9b, 0x17);
        this.TaskException.TabIndex = 1;
        this.TaskException.Text = "TaskException";
        this.TaskException.UseVisualStyleBackColor = true;
        this.TaskException.Click += new EventHandler(this.TaskException_Click);
        this.VoidException.Location = new Point(0xda, 0x16d);
        this.VoidException.Name = "VoidException";
        this.VoidException.Size = new Size(0xab, 0x17);
        this.VoidException.TabIndex = 2;
        this.VoidException.Text = "VoidException";
        this.VoidException.UseVisualStyleBackColor = true;
        this.VoidException.Click += new EventHandler(this.VoidException_Click);
        base.AutoScaleDimensions = new SizeF(6f, 13f);
        base.AutoScaleMode = AutoScaleMode.Font;
        base.ClientSize = new Size(550, 430);
        base.Controls.Add(this.VoidException);
        base.Controls.Add(this.TaskException);
        base.Controls.Add(this.textBox1);
        base.Name = "Form1";
        this.Text = "Form1";
        base.ResumeLayout(false);
        base.PerformLayout();
    }

    [DebuggerStepThrough, AsyncStateMachine(typeof(<TaskException_Click>d__4))]
    private void TaskException_Click(object sender, EventArgs e)
    {
        <TaskException_Click>d__4 d__;
        d__.<>4__this = this;
        d__.sender = sender;
        d__.e = e;
        d__.<>t__builder = AsyncVoidMethodBuilder.Create();
        d__.<>1__state = -1;
        d__.<>t__builder.Start<<TaskException_Click>d__4>(ref d__);
    }

    private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        MethodInvoker method = null;
        e.SetObserved();
        if (base.InvokeRequired)
        {
            if (method == null)
            {
                method = (MethodInvoker) (() => (this.textBox1.Text = "Unobserved Exception caught " + e.Exception.Message));
            }
            base.BeginInvoke(method);
        }
        else
        {
            this.textBox1.Text = "Unobserved Exception caught " + e.Exception.Message;
        }
    }

    [AsyncStateMachine(typeof(<TaskThrowAnException>d__6)), DebuggerStepThrough]
    private Task TaskThrowAnException()
    {
        <TaskThrowAnException>d__6 d__;
        d__.<>4__this = this;
        d__.<>t__builder = AsyncTaskMethodBuilder.Create();
        d__.<>1__state = -1;
        d__.<>t__builder.Start<<TaskThrowAnException>d__6>(ref d__);
        return d__.<>t__builder.Task;
    }

    [DebuggerStepThrough, AsyncStateMachine(typeof(<VoidException_Click>d__8))]
    private void VoidException_Click(object sender, EventArgs e)
    {
        <VoidException_Click>d__8 d__;
        d__.<>4__this = this;
        d__.sender = sender;
        d__.e = e;
        d__.<>t__builder = AsyncVoidMethodBuilder.Create();
        d__.<>1__state = -1;
        d__.<>t__builder.Start<<VoidException_Click>d__8>(ref d__);
    }

    [AsyncStateMachine(typeof(<VoidThrowAnException>d__a)), DebuggerStepThrough]
    private void VoidThrowAnException()
    {
        <VoidThrowAnException>d__a _a;
        _a.<>4__this = this;
        _a.<>t__builder = AsyncVoidMethodBuilder.Create();
        _a.<>1__state = -1;
        _a.<>t__builder.Start<<VoidThrowAnException>d__a>(ref _a);
    }

    [CompilerGenerated]
    private struct <TaskException_Click>d__4 : IAsyncStateMachine
    {
        public int <>1__state;
        public Form1 <>4__this;
        public AsyncVoidMethodBuilder <>t__builder;
        public EventArgs e;
        public object sender;

        private void MoveNext()
        {
            try
            {
                if (this.<>1__state != -3)
                {
                    this.<>4__this.textBox1.Text = "";
                    try
                    {
                        Task task = this.<>4__this.TaskThrowAnException();
                        this.<>4__this.textBox1.Text = "done";
                        task = null;
                    }
                    catch (Exception)
                    {
                        this.<>4__this.textBox1.Text = "Exception caught";
                    }
                    Thread.Sleep(100);
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                }
            }
            catch (Exception exception2)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception2);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult();
        }

        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine param0)
        {
            this.<>t__builder.SetStateMachine(param0);
        }
    }

    [CompilerGenerated]
    private struct <TaskThrowAnException>d__6 : IAsyncStateMachine
    {
        public int <>1__state;
        public Form1 <>4__this;
        public AsyncTaskMethodBuilder <>t__builder;

        private void MoveNext()
        {
            try
            {
                if (this.<>1__state != -3)
                {
                    this.<>4__this.i++;
                    throw new Exception("Task" + this.<>4__this.i.ToString());
                }
            }
            catch (Exception exception)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult();
        }

        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine param0)
        {
            this.<>t__builder.SetStateMachine(param0);
        }
    }

    [CompilerGenerated]
    private struct <VoidException_Click>d__8 : IAsyncStateMachine
    {
        public int <>1__state;
        public Form1 <>4__this;
        public AsyncVoidMethodBuilder <>t__builder;
        public EventArgs e;
        public object sender;

        private void MoveNext()
        {
            try
            {
                if (this.<>1__state != -3)
                {
                    this.<>4__this.textBox1.Text = "";
                    try
                    {
                        this.<>4__this.VoidThrowAnException();
                        this.<>4__this.textBox1.Text = "done";
                    }
                    catch (Exception)
                    {
                        this.<>4__this.textBox1.Text = "Exception caught";
                    }
                }
            }
            catch (Exception exception2)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception2);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult();
        }

        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine param0)
        {
            this.<>t__builder.SetStateMachine(param0);
        }
    }

    [CompilerGenerated]
    private struct <VoidThrowAnException>d__a : IAsyncStateMachine
    {
        public int <>1__state;
        public Form1 <>4__this;
        public AsyncVoidMethodBuilder <>t__builder;

        private void MoveNext()
        {
            try
            {
                if (this.<>1__state != -3)
                {
                    SynchronizationContext current = SynchronizationContext.Current;
                    throw new Exception("Void");
                }
            }
            catch (Exception exception)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult();
        }

        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine param0)
        {
            this.<>t__builder.SetStateMachine(param0);
        }
    }
}

}

谢谢Ned,如果我想添加一个t,是的。等等,单击事件中捕获了异常。但事实并非如此,这是无法观察到的。如果任务只需要抛出一个异常,那么它怎么可能没有完成呢?