Windows窗体,异步任务异常捕获

时间:2014-05-22 10:00:15

标签: asynchronous task

我有一个表单,2个按钮,1个文本框。按钮1处理TaskException_click。 我想要做的是理解异步任务/虚空差异。但检查多个例子我仍然不理解或让它工作。在我的代码下面。 当我单击taskexception按钮时,不执行unobservedtaskexception(我预期)。 当我再次单击它时,将执行该事件,但第一次单击除外。但是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");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

对于TaskException案例,异常存储在Task中,这是返回async的{​​{1}}方法的预期行为。如果您希望抛出异常,则需要等待Task或致电Task上的ResultWait()来观察异常。

如果异常未被观察到,那么当Task完成时它应该被抛出,我唯一可以得出的结论是,当你调用

时,某个任务没有被完成
Task

我也不确定为什么局部变量不是GCed,如果添加另一个按钮并将上面的代码放在按钮处理程序中(例如Thread.Sleep(100); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); ),一切都按预期工作。我认为生成的代码必须以某种方式链接到任务变量,但我找不到任何链接。

以下是Reflector生成的代码:

Clear_Click

}