Timer.Elapsed引发的异常未由尝试的全局异常事件处理程序Visual C#捕获 [英] Exception raised by Timer.Elapsed not caught by attempted global exception event handler Visual C#

查看:248
本文介绍了Timer.Elapsed引发的异常未由尝试的全局异常事件处理程序Visual C#捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已尽最大努力简化了此问题,以找出问题所在.我假设这与在单独线程中引发的异常有关

让我们有一个WindowsFormApp.

Let there be a WindowsFormApp.

假设Program类的源代码如下

Suppose the Program class source looks like this

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionOccurred);
        Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(UnhandledExceptionOccurred);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public static void UnhandledExceptionOccurred(object sender, UnhandledExceptionEventArgs e)
    {
        var x = (Exception)e.ExceptionObject;
        MessageBox.Show("Unhandled Exception\r\n" + x.Message);

    }

    public static void UnhandledExceptionOccurred(object sender, ThreadExceptionEventArgs e_thread)
    {
        var x = e_thread.Exception;
        MessageBox.Show("Thread Exception\r\n" + x.Message);
    }
}

对不起,如果这已经不堪重负了.让我尝试简化这篇文章中为积累知识而发生的事情.

Sorry if this is already overwhelming. Let me attempt to simplify for those happening upon this post for the accumulation of knowledge.

静态方法UnhandledExceptionOccurred()具有一个替代.这些方法用作未处理线程异常和来自主线程的未处理异常的事件处理程序. (如果这不正确,我想对此进行更正,但这是我的理解方式).

The static method UnhandledExceptionOccurred() has one override. These methods are used as event handlers for Unhandled Thread Exceptions, and Unhandled Exceptions coming from the main thread. (I would like to be corrected on this if this it not correct, but this is how I understand it).

假设在主窗体中,单击按钮时会引发异常

Suppose in the main form, when a button is clicked an exception is thrown

private void button1_Click(object sender, EventArgs e)
{
    throw new Exception("Exception 1");
}

假设单击该按钮.消息框显示为

Suppose the button is clicked. The Exception is caught just fine with the message box reading

线程异常异常1"

"Thread Exception Exception 1"

现在(几乎完成了)假设我在Form1的构造函数中创建了一个System.Timers.Timer,其间隔为5000毫秒,并为其事件发生后的事件处理程序抛出了异常.

Now (almost done) suppose in the Constructor of Form1, I create a System.Timers.Timer, having an interval of 5000 miliseconds, with an event handler for it's elapsed event which throws an exception.

System.Timers.Timer T;
public Form1()
{
    InitializeComponent();
    T = new System.Timers.Timer();
    T.Interval = 5000; //Miliseconds;
    T.Elapsed += new ElapsedEventHandler(TimerElapsed);
    T.Start();
}

事件处理程序:

public void TimerElapsed(object sender, ElapsedEventArgs e)
{
    T.Stop();
    throw new Exception("Exception From Timer Elapsed");
}

现在假设表单已启动,并且经过了5秒钟.

Now suppose the form is started, and 5 seconds pass.

没有消息框出现,并且没有WindowsFormError框弹出.该程序默默地吞下了异常,我能够单击前面提到的按钮,并使消息框像以前一样显示.

No messagebox appears, and no WindowsFormError box pops up. The program silently swallows the exception, and I am able to click the button mentioned before and cause a messagebox to appear as before.

这是怎么回事?

我知道这很可能与计时器正在进行的线程处理有关.我已经搜索了并且还没有找到访问计时器正在使用的线程内部的方法,以便可以为其UnhandledException和ThreadException事件添加一些事件处理程序.

I know that this is likely related to a threading thing going on with the timer. I have searched and searched and have yet to find a way to access the internals of the thread that the timer is using so that I can add some event handlers for its UnhandledException and ThreadException events.

也许我可以使用System.Threading.Timers Timer.

我注意到这种计时器的构造函数使用CallbackMethod吗? (什么是回调方法?)也许可以使用该回调方法将未处理的异常路由回MainUI线程?

I noticed that the constructor for this type of timer takes a CallbackMethod? (What is a callback method?) Perhaps this callback method could be used to route back unhandled exceptions to the MainUI thread?

任何/所有输入都值得赞赏.

Any/All input is appreciated.

推荐答案

将System.Timers.Timer SyncronyzingObject设置为主要形式可以解决此问题.

Setting the System.Timers.Timer SyncronyzingObject to the main form fixes this issue.

System.Timers.Timer T;
public Form1()
{
    InitializeComponent();
    T = new System.Timers.Timer();
    T.SynchronizingObject = this;
    T.Interval = 5000; //Miliseconds;
    T.Elapsed += new ElapsedEventHandler(TimerElapsed);
    T.Start();
}

当可视Windows窗体组件处理了Elapsed事件时, 例如按钮,通过系统线程访问组件 池可能会导致异常,或者可能无法正常工作.避免这个 通过将SynchronizingObject设置为Windows Forms组件来实现效果, 这导致处理Elapsed事件的方法被调用 在其上创建组件的相同线程. - Microsoft.Com

When the Elapsed event is handled by a visual Windows Forms component, such as a button, accessing the component through the system-thread pool might result in an exception or just might not work. Avoid this effect by setting SynchronizingObject to a Windows Forms component, which causes the method that handles the Elapsed event to be called on the same thread that the component was created on. -- Microsoft.Com

这篇关于Timer.Elapsed引发的异常未由尝试的全局异常事件处理程序Visual C#捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆