UI线程.Invoke()导致句柄泄漏? [英] UI Thread .Invoke() causing handle leak?
问题描述
在什么情况下,使用委托和.InvokeRequired
时从非UI线程更新UI控件可能导致进程的句柄不断增加?
In what circumstances would updating a UI control from a non-UI thread could cause the processes' handles to continually increase, when using a delegate and .InvokeRequired
?
例如:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
if (someControl.InvokeRequired)
{
someControl.Invoke(new DelegateUIUpdate(UIUpdate));
return;
}
// do something with someControl
}
在循环中或按计时器间隔调用此方法时,程序的句柄会不断增加.
When this is called in a loop or on timer intervals, the handles for the program consistently increase.
如果以上内容已被注释掉并作如下修改:
If the above is commented out and amended as such:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
//if (someControl.InvokeRequired)
//{
// someControl.Invoke(new DelegateUIUpdate(UIUpdate));
// return;
//}
CheckForIllegalCrossThreadCalls = false;
// do something with someControl
}
...然后使句柄 stop 递增,但是我当然不想允许跨线程调用.
...then the handles stop incrementing, however I don't want to allow cross thread calls, of course.
以下是显示手柄增加的示例:
Here is a sample that shows the handles increase:
Thread thread;
private delegate void UpdateGUI();
bool UpdateTheGui = false;
public Form1()
{
InitializeComponent();
thread = new Thread(new ThreadStart(MyThreadLoop));
thread.Start();
}
private void MyThreadLoop()
{
while (true)
{
Thread.Sleep(500);
if (UpdateTheGui)
{
UpdateTheGui = false;
UpdateTheGuiNow();
}
}
}
private void UpdateTheGuiNow()
{
if (label1.InvokeRequired)
{
label1.Invoke(new UpdateGUI(UpdateTheGuiNow));
return;
}
label1.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
label2.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
label3.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
}
private void btnInvoke_Click(object sender, EventArgs e)
{
UpdateTheGui = true;
}
推荐答案
Control.Invoke()方法不使用任何句柄.但是,显然是从线程中调用此代码的.线程确实消耗其中的5个句柄.
The Control.Invoke() method doesn't consume any handles. However, this code is clearly called from a thread. A Thread does consume handles, 5 of them.
尽管Thread类应该有一个Dispose()方法,但它没有.那可能是设计使然,对于线程池线程来说,可靠地,不可能地调用是非常困难的.终结器释放线程所需的5个句柄.如果终结器从不运行,您的程序将需要不断增加的句柄.
The Thread class doesn't have a Dispose() method, although it ought to have one. That was probably by design, it would be very difficult to call reliably, impossibly so for threadpool threads. The 5 handles that a thread requires are released by the finalizer. Your program will require ever increasing amounts of handles if the finalizer never runs.
不让finalizer运行很不寻常.您将必须有一个程序,该程序可以启动许多线程,但不会分配大量内存.这往往仅在静态测试中发生.您可以使用Perfmon.exe诊断这种情况,使用.NET内存性能计数器并检查是否已完成gen#0收集.
Not getting the finalizer to run is quite unusual. You would have to have a program that starts a lot of threads but doesn't allocate a lot of memory. This tends to only happen in static tests. You can diagnose this condition with Perfmon.exe, use the .NET memory performance counters and check if gen #0 collections are being done.
如果这在生产程序中发生,那么您必须自己调用GC.Collect(),以免发生句柄泄漏.
If this happens in a production program then you'll have to call GC.Collect() yourself to avoid a runaway handle leak.
这篇关于UI线程.Invoke()导致句柄泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!