То, при каких обстоятельствах был бы, обновляя управление UI от потока неUI, могло заставить дескрипторы процессов постоянно увеличиваться при использовании делегата и .InvokeRequired
?
Например:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
if (someControl.InvokeRequired)
{
someControl.Invoke(new DelegateUIUpdate(UIUpdate));
return;
}
// do something with someControl
}
Когда это называют в цикле или на интервалах таймера, дескрипторы для программы последовательно увеличиваются.
Править:
Если вышеупомянутое комментируется и исправляется как таковое:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
//if (someControl.InvokeRequired)
//{
// someControl.Invoke(new DelegateUIUpdate(UIUpdate));
// return;
//}
CheckForIllegalCrossThreadCalls = false;
// do something with someControl
}
... затем дескрипторы прекращают увеличивать, однако я не хочу позволять перекрестные вызовы потока, конечно.
РЕДАКТИРОВАНИЕ 2:
Вот образец, который показывает увеличение дескрипторов:
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.
У класса Thread нет метода Dispose (), хотя он должен быть. Вероятно, это было задумано, это было бы очень сложно вызвать надежно, что невозможно для потоков threadpool. 5 дескрипторов, которые требуются потоку, освобождаются финализатором. Ваша программа потребует постоянно увеличивающегося количества дескрипторов, если финализатор никогда не запускается.
Не запускать финализатор довольно необычно. У вас должна быть программа, которая запускает много потоков, но не выделяет много памяти. Обычно это происходит только в статических тестах.Вы можете диагностировать это состояние с помощью Perfmon.exe, использовать счетчики производительности памяти .NET и проверить, выполняются ли сборы Gen # 0.
Если это происходит в производственной программе, вам придется вызвать GC.Collect () самостоятельно, чтобы избежать утечки неконтролируемого дескриптора.
Это стандартный шаблон для использования Invoke
для маршалинга обновлений в поток пользовательского интерфейса.
Вы уверены, что ваша проблема не вызвана другим кодом в вашем приложении, который не включен в ваш вопрос?
Я не думаю, что это связано. Возможно, просто ждем, пока сборщик мусора избавится от вновь выделенных объектов внутри Invoke ().
На самом деле я вижу ту же проблему, что и JYelton. У меня такой же вызов из потока для обновления пользовательского интерфейса.
Как только вызывается строка someControl.Invoke (new DelegateUIUpdate (UIUpdate));
, дескриптор увеличивается на единицу. В вызове определенно есть какая-то утечка, но я понятия не имею, что ее вызывает. Это было проверено на нескольких системах.