Поток UI.Invoke () порождение утечки дескриптора?

То, при каких обстоятельствах был бы, обновляя управление 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;
}
8
задан JYelton 15 June 2010 в 22:05
поделиться

4 ответа

Метод Control.Invoke () не использует никаких дескрипторов. Однако этот код явно вызывается из потока. Поток использует дескрипторы, из них 5.

У класса Thread нет метода Dispose (), хотя он должен быть. Вероятно, это было задумано, это было бы очень сложно вызвать надежно, что невозможно для потоков threadpool. 5 дескрипторов, которые требуются потоку, освобождаются финализатором. Ваша программа потребует постоянно увеличивающегося количества дескрипторов, если финализатор никогда не запускается.

Не запускать финализатор довольно необычно. У вас должна быть программа, которая запускает много потоков, но не выделяет много памяти. Обычно это происходит только в статических тестах.Вы можете диагностировать это состояние с помощью Perfmon.exe, использовать счетчики производительности памяти .NET и проверить, выполняются ли сборы Gen # 0.

Если это происходит в производственной программе, вам придется вызвать GC.Collect () самостоятельно, чтобы избежать утечки неконтролируемого дескриптора.

3
ответ дан 5 December 2019 в 15:19
поделиться

Это стандартный шаблон для использования Invoke для маршалинга обновлений в поток пользовательского интерфейса.

Вы уверены, что ваша проблема не вызвана другим кодом в вашем приложении, который не включен в ваш вопрос?

0
ответ дан 5 December 2019 в 15:19
поделиться

Я не думаю, что это связано. Возможно, просто ждем, пока сборщик мусора избавится от вновь выделенных объектов внутри Invoke ().

0
ответ дан 5 December 2019 в 15:19
поделиться

На самом деле я вижу ту же проблему, что и JYelton. У меня такой же вызов из потока для обновления пользовательского интерфейса.

Как только вызывается строка someControl.Invoke (new DelegateUIUpdate (UIUpdate)); , дескриптор увеличивается на единицу. В вызове определенно есть какая-то утечка, но я понятия не имею, что ее вызывает. Это было проверено на нескольких системах.

1
ответ дан 5 December 2019 в 15:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: