gpt4 book ai didi

c# - 所有 GUI 线程的 Application.ThreadException 事件

转载 作者:行者123 更新时间:2023-11-30 12:26:48 25 4
gpt4 key购买 nike

我有一个 WinForms 应用程序,它创建了多个表单,每个表单都在自己的 GUI 线程(而不是主 GUI 线程)中。我想处理所有这些表单的未处理异常事件 (Application.ThreadException) 以处理任何错误。我还想处理来自工作线程的异常 - 这一点似乎工作正常,但我仍然无法处理来自 GUI 线程的异常:

程序.cs:

[STAThread]
static void Main()
{
AttachExceptionHandlers();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static void AttachExceptionHandlers()
{
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Dispatcher.CurrentDispatcher.UnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(CurrentDispatcher_UnhandledException);
}

Form1.cs:

//GUI Thread Crash
private void button1_Click(object sender, EventArgs e)
{
object a = null;
a.ToString();
}
//Worker Thread Crash
private void button2_Click(object sender, EventArgs e)
{
Thread myThread = new Thread(() =>
{
object a = null;
a.ToString();
});
myThread.Start();
myThread.Join();
}
//New Thread, New Gui Crash
private void button3_Click(object sender, EventArgs e)
{
Thread myThread = new Thread(() =>
{
using (CrashingForm form = new CrashingForm()) //Crashing Form Crashes in it's FormLoad event.
{
Application.Run(form);
}
});
myThread.Start();
myThread.Join();
}

此代码将在前 2 个实例(GUI 线程崩溃和工作线程崩溃)中调用我的异常处理程序,但不会处理创建新 GUI 线程的第三个实例。我发现如果我调用 Program.AttachExceptionHandlers();在 Application.Run(form) 行之前,一切正常,但这是不可取的,因为我必须实现一些逻辑以确保在我们调用在每个线程上创建表单之前调用 Program.AttachExceptionHandlers() (如果在线程上创建表单后调用,则对 Application.SetUnhandledExceptionMode 的调用失败)。

此示例是较大部分代码的一部分,理想情况下,它会为我的代码用户提供一个简单的 API,以便在他们的应用程序开始时调用(如在 Program.cs 中)以附加异常处理程序。然后,异常处理程序会做一些魔术来记录有关在应用程序终止之前抛出的异常的详细信息。因此,告诉用户他们必须在每次创建新的 GUI 线程时进行跟踪(工作线程似乎不受此问题的影响)并重新附加 Application.ThreadException 处理程序并不是一个干净的解决方案。

是否有另一种方法可以实现这一点,而无需在每次创建新的 GUI 线程时都重新注册 Application.ThreadException 事件?

最佳答案

Is there another way to achieve this, without having to re registerer for the Application.ThreadException event each time a new GUI thread is created?

我什么都不知道,我和我的队友已经花了很多时间调查它。在涉及如何创建/管理/销毁多个消息泵时,.NET WinForms 似乎不是很固执己见。

除了 Retlang's 之外,我们还使用类似于下面的框架方法WinFormsFiber。

using System;
using System.Threading;
using System.Windows.Forms;

internal static class Program
{
[STAThread]
private static void Main()
{
CreateFormAndStartMessagePump(() => CreateForm("first"), OnException, OnException, false, "pumpThread1");
CreateFormAndStartMessagePump(() => CreateForm("second"), OnException, OnException, false, "pumpThread2");
// note app shutdown not handled here
}

private static T CreateFormAndStartMessagePump<T>(
Func<T> createForm,
ThreadExceptionEventHandler onThreadException,
UnhandledExceptionEventHandler onDomainException,
bool isBackground,
string name) where T : Form
{
var latch = new ManualResetEvent(false);
T form = null;
var thread = new Thread(ts =>
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += onThreadException;
AppDomain.CurrentDomain.UnhandledException += onDomainException;
form = createForm();
latch.Set();
Application.Run();
})
{
IsBackground = isBackground,
Name = name
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
latch.WaitOne();
return form;
}

private static Form CreateForm(string name)
{
var form = new Form();
form.Text = name;
form.Show();
return form;
}

private static void OnException(object sender, UnhandledExceptionEventArgs e)
{
// ...
}

private static void OnException(object sender, ThreadExceptionEventArgs e)
{
// ...
}
}

关于c# - 所有 GUI 线程的 Application.ThreadException 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27505161/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com