C# 调用表单时的ObjectDisposedException';s在没有';我没有被处置
我们从一个尚未处理的表单上调用C# 调用表单时的ObjectDisposedException';s在没有';我没有被处置,c#,winforms,invoke,C#,Winforms,Invoke,我们从一个尚未处理的表单上调用Invoke得到一个ObjectDisposedException。下面是一些演示问题的示例代码: public partial class Form2 : Form { void Form2_Load(object sender, EventArgs e) { // Start a task that does an Invoke on this control Task.Factory.StartNew(TaskW
Invoke
得到一个ObjectDisposedException
。下面是一些演示问题的示例代码:
public partial class Form2 : Form
{
void Form2_Load(object sender, EventArgs e)
{
// Start a task that does an Invoke on this control
Task.Factory.StartNew(TaskWork);
// Sleep here long enough to allow the task that does the Invoke
// to execute to the point where it has:
// a. Posted the message and
// b. is waiting
Thread.Sleep(500);
// Cause ShowDialog to return by setting the DialogResult
DialogResult = DialogResult.OK;
}
void TaskWork()
{
// This call doesn't return, but instead throws an ObjectDisposedException
this.Invoke((MethodInvoker)(() => MessageBox.Show("Invoke succeeded")));
}
}
以下是我从未关闭的Form1(主窗体)的调用代码:
public partial class Form1 : Form
{
Form2 m_form2 = new Form2();
void Form1_Load(object sender, EventArgs e)
{
// Call ShowDialog, but don't dispose it.
m_form2.ShowDialog();
// Cause the finalizers to run. This causes an AggregateException to be thrown
// due to the unhandled ObjectDisposedException from the Task.
GC.Collect();
}
}
我们深入到Microsoft源代码,发现异常是在调用DestroyHandle时创建的(如下所示)。ShowDialog正在完成时调用DestroyHandle
从源.NET\4\DEVDIV\u TFS\Dev10\Releases\RTMRel\ndp\fx\src\WinForms\Managed\System\WinForms\Control.cs\1305376\Control.cs:
protected virtual void DestroyHandle() {
// ...
// If we're not recreating the handle, then any items in the thread callback list will
// be orphaned. An orphaned item is bad, because it will cause the thread to never
// wake up. So, we put exceptions into all these items and wake up all threads.
// If we are recreating the handle, then we're fine because recreation will re-post
// the thread callback message to the new handle for us.
//
if (!RecreatingHandle) {
if (threadCallbackList != null) {
lock (threadCallbackList) {
Exception ex = new System.ObjectDisposedException(GetType().Name);
while (threadCallbackList.Count > 0) {
ThreadMethodEntry entry = (ThreadMethodEntry)threadCallbackList.Dequeue();
entry.exception = ex;
entry.Complete();
}
}
}
}
// ...
}
问题:
.ShowDialog()
会创建一个新句柄.ShowDialog()
之后尝试执行调用
,则会出现InvalidOperationException,指出“在创建窗口句柄之前,无法对控件调用Invoke或BeginInvoke。”.ShowDialog()
之后,我访问句柄
属性,然后执行调用
,则该操作将成功在这里您遇到了一个棘手的问题,但一般策略必须始终是确保在允许表单关闭之前完成或终止线程。更多信息请访问。感谢您的回答和链接。非常有用。我不明白的是,为什么需要破坏把手来隐藏窗口。如果我要连续执行几个ShowDialog,那么似乎没有必要销毁句柄。我错过什么了吗?我一直以为把手只有在处理后才会被破坏。我只是想,你对此无能为力。隐藏对话框也会破坏本机窗口。啊,我不知道。谢谢在查看一个类似的问题(关闭表单调用invoke)并尝试检查表单及其一个控件上的
IsDisposed
时,仍然得到invalidooperationexception
,我发现在这种情况下disposed
是正确的,即使IsDisposed
不是。