
[英]Why isn't Dispatcher.BeginInvoke working when re-creating my WPF DataGrid columns?
[英]Why isn't the action in BeginInvoke executed when a control is disposed before the event loop starts?
WinForms(NET Core 和 Framework)中的以下代码在运行 Application.DoEvents 时不会尝试 BeginInvoke 中的操作:
namespace BeginInvokeTest
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
bool executed;
var form = new Form();
form.Show();
form.BeginInvoke(() => { executed = true; });
form.Dispose();
Application.DoEvents();
}
}
}
但是,如果我在 Application.DoEvents 之后移动 form.Dispose,则执行该操作。 所以我知道如果在启动消息循环之前处置了拥有控件,则 BeginInvoke 排队的消息将被忽略。
有谁知道在 WinForms 中的哪个位置强制/实施了这种行为; 释放控件时,WinForms 会从队列中删除消息吗?
(查看了 GitHub 中的源代码,但无法锻炼发生这种情况的位置/方式)
谢谢!
您要查找的代码在Control.DestoryHandle
中,由Control.Dispose
调用
// 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();
}
}
}
}
如您所见,如果未重新创建句柄,则所有尚未调度的剩余回调都将设置为具有异常。 因为这是异步的,所以除非您调用EndInvoke
,否则您不会看到异常。
如果回调已经完成,您也不会看到任何异常。 当您调用DoEvents
时,队列中的任何 window 消息都会被抽出。 调用的回调通过 window 消息队列调度,因此所有回调都在您调用DoEvents
时完成。 所以当你之后Dispose
时,即使你调用EndInvoke
也不例外,因为回调已经完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.