.net 避免`Control.Invoke`和析构函数之间的死锁,为UserControl重新访问

.net 避免`Control.Invoke`和析构函数之间的死锁,为UserControl重新访问,.net,winforms,deadlock,invoke,dispose,.net,Winforms,Deadlock,Invoke,Dispose,我遇到了我所问问题的变体。我没有扩展类System.Windows.Form,而是扩展类System.Windows.UserControl,它没有FormClosing事件 我考虑在用户控件中添加一个Close方法,在该方法中我告诉本机线程停止。当它停止时,它会向用户控件引发一个事件,该控件会对自身调用Dispose。这种方法的问题是,从对象调用Dispose进行Dispose(自杀?)似乎是一种糟糕的做法,我不得不编写一个不做任何事情的终结器(以避免重复处理),这感觉更糟 建议 更新:我的用

我遇到了我所问问题的变体。我没有扩展类
System.Windows.Form
,而是扩展类
System.Windows.UserControl
,它没有
FormClosing
事件

我考虑在用户控件中添加一个
Close
方法,在该方法中我告诉本机线程停止。当它停止时,它会向用户控件引发一个事件,该控件会对自身调用
Dispose
。这种方法的问题是,从对象调用
Dispose
进行Dispose(自杀?)似乎是一种糟糕的做法,我不得不编写一个不做任何事情的终结器(以避免重复处理),这感觉更糟

建议


更新:我的用户控件存在于一个扩展了
System.Windows.Forms.ToolStripControlHost的类中,该类的一个实例存在于主应用程序窗体中。

我会向用户控件添加某种方法,并在窗体
FormClosing
事件中调用它

用户控件中的方法将被阻塞,因此在处理完成之前不会返回

但是,您可以在关闭事件中取消关闭,禁用表单,在后台执行某些操作,完成后,从代码中关闭表单。例如:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // if disposed, close as usual
    if (myControl == null || myControl.Disposed) return;
    // disable the form so nothing can be done while
    // were asynchronously disposing the form...
    this.Enabled = false;
    e.Cancel = true;
    var context = TaskScheduler.FromCurrentSynchronizationContext();
    Task.Factory.StartNew(()=>myControl.Dispose())
        .ContinueWith(a=>Close(), context);
}

用户控件的生存期是否由其主机管理?主机是windows窗体吗?当您提到窗体的
FormClosing
事件时,我假定您指的是包含包含用户控件的主机的窗体,不是吗?请参阅更新;
.ContinueWith
将在窗体的线程上执行,而
Dispose
将在线程池线程上执行。我无法阻止控件的Dispose,因为这将导致
控件.Invoke
和本机对象析构函数之间的潜在死锁(请参阅原始问题)。在处置本机对象之前,我必须确保本机对象已完成其关闭过程(其线程已退出)。我想我将从您的示例中删除最后两行,并处理当本机线程一直到主窗体结束时触发的事件。在该事件的处理程序中,我可以继续关闭主窗体。你认为呢?那会完成同样的事情。在你的情况下,我不确定细节。我的示例基本上使对“myControl.Dispose”调用的完成成为一个事件。因此,您可以通过响应控件的事件并调用“Form.Close()”来执行相同的操作。