gpt4 book ai didi

c# - System.Drawing.dll 中出现类型为 'System.ApplicationException' 的未处理异常

转载 作者:可可西里 更新时间:2023-11-01 03:11:30 24 4
gpt4 key购买 nike

我有一个 winforms 应用程序。在开发模式下,当从 Visual Studio .NET 2003 进行调试时(是的,我知道它很旧,但这是一个遗留项目),当我尝试打开一个新窗体时出现此错误。为了打开一个新表单,我获取了该表单的一个实例,然后我调用了 ShowDialog() 方法,例如:

frmTest test = new frmTest(here my parameters);
test.ShowDialog();

如果我在调试时按 F11(进入)它不会崩溃,但如果在我实例化表单的行中我按 F10 进入下一行,即 test.ShowDialog(),那么它会崩溃显示这个错误。

完整的报错是:

"An unhandled exception of type 'System.ApplicationException' occurred in System.drawing.dll. Additional Information: An attempt was made to free a mutual exclusion that does not belong to the process"

我已经翻译了最后一部分:附加信息......因为它以西类牙语出现。

我用参数实例化的形式,它的构造函数,包括初始化一些变量,例如:

public frmTest(string param1, string param2)
{
InitializeComponent();

this.param1 = param1;
this.param2 = param2;
}

private void frmTest_Load(object sender, EventArgs e)
{
// here I call a remote webservice asynchronously.
}

我的表单“frmTest”还有四个图片框、一个标签和一个按钮。其中三个图片框包含一个 png 图像(它在设计时通过 Image 属性分配),最后一个图片框包含一个动画 gif,也在设计时通过 Image 属性加载。可能是这些图片导致的错误?

最佳答案

TL;DR: Your web request handler will execute on a different thread. Ensure you don't do anything that isn't thread-safe in that handler. You can use Invoke to dispatch your callback handler's code to the main thread.

诊断

这里的问题几乎肯定隐藏在您的异步调用的缺失细节中。

// here I call a remote webservice asynchronously.

Asynchronously 有点过于模糊,无法确定到底 发生了什么,但是很有可能您正在使用的异步机制已经执行了它的 < strong>在主 UI 线程的不同线程上回调。

概览

这在 .NET 模型中很常见。 .NET 模型中的异步 I/O 使用线程池中的线程通过 I/O Completion Ports (IOCP) 处理 I/O .这意味着当 Socket.BeginReceiveWebRequest.BeginGetResponse 之类的调用(或任何内部使用类似技术的 .NET 异步 Web 请求)完成时,回调将在线程池中的一个线程上执行不是主线程。这可能会让您感到惊讶,因为您没有主动创建另一个线程;您刚刚参与了异步调用。

您必须非常小心在 Web 请求的回调中执行的操作,因为除了主 UI 线程外,任何线程都不允许执行许多用户界面/Windows 窗体操作。同样,导致问题的可能不是 UI 本身,您可能刚刚访问了一些非线程安全的资源或对象。如果您不小心处理多线程,许多看似无害的事情可能会导致崩溃或异常。

解决问题:

如果有疑问,请在您的回调中尽早分派(dispatch)(也称为 Invoke)您的处理程序中的代码,以便它在主线程上运行。

执行此操作的常见模式如下所示。

假设你打了这样一个电话:

IAsyncResult result = (IAsyncResult myHttpWebRequest.BeginGetResponse(
new AsyncCallback(RespoCallback), myRequestState);

处理程序可以这样设置:

private static void RespCallback(IAsyncResult asynchronousResult)
{
// THIS IS NOT GOING TO WORK BECAUSE WE ARE ON THE WRONG THREAD. e.g.:
this.label1.Text = "OK"; // BOOM! :(
}

相反,将任何必要的处理分派(dispatch)回主线程。

private static void RespCallback(IAsyncResult asynchronousResult)
{
this.Invoke((MethodInvoker) delegate {
// This block of code will run on the main thread.
// It is safe to do UI things now. e.g.:
this.label1.Text = "OK"; // HOORAY! :)
});
}

建议将此作为一般最佳实践。我不是是说立即将所有处理程序分派(dispatch)回主线程。一种尺寸适合所有尺寸。您真的应该查看您在处理程序中执行的操作的具体细节,并确保您没有执行特定于线程的操作。但我说,如果您没有对您的异步处理程序正在做什么进行任何解释,问题可能会通过 invoking 解决。主线程上的处理程序代码。

注意:当然,要使用此技术解决您的问题,它需要您的主线程正在运行。如果您使用类似 this example 中的(错误)技术阻塞了主线程那么您将不得不重新设计应用程序的一部分。这是一个需要更大返工的示例:

// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);

// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);

// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // *** DANGER: This blocks the main thread, the IO thread
// won't be able to dispatch any work to it via `invoke`

注意到 WaitOne 调用了吗?这会阻止正在执行的线程的执行。如果此代码在主线程上执行,则主线程将被阻塞,直到 WebRequest 完成。您将不得不重新设计,这样您就不会阻塞主线程(我的建议),或者您更仔细地检查您的回调处理程序以了解为什么它正在做的事情与其他线程冲突。

关于c# - System.Drawing.dll 中出现类型为 'System.ApplicationException' 的未处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44936177/

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