Использование Control.Invoke () вместо блокировки (Control) - PullRequest
2 голосов
/ 28 сентября 2011

Я работаю над многопоточным приложением, которое должно обновлять элемент управления Winforms по мере его развития (A DataGridView). Чтобы предотвратить множественный доступ к одному и тому же общему ресурсу, я начал со следующей структуры блокировки:

if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
    while (DGV.Columns.Count < DesiredColumnCount)
    {
        DGV.Columns.Add(newColumn);
    }
}

Затем я понял, что, поскольку DGV был создан в потоке пользовательского интерфейса, он должен быть .Invoke() 'd. Это изменяет код на:

if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
    DGV.Invoke(new MethodInvoker(() =>
        {
            while (DGV.Columns.Count < DesiredColumnCount)
            {
                DGV.Columns.Add(newColumn);
            }
        }
}

Мой вопрос: это не избыточно? lock будет блокировать рабочий поток до тех пор, пока он не получит монопольный доступ к DGV, а Invoke() будет блокировать рабочий поток до тех пор, пока поток пользовательского интерфейса не сможет подобрать запрос на вызов и выполнить код. Разве я не могу просто получить, используя только Invoke()?

(Это главный вопрос. Конечно, если в приведенном выше коде есть какие-либо другие многопоточные грехи, пожалуйста, прокомментируйте)

1 Ответ

3 голосов
/ 28 сентября 2011

Это немного избыточно, вызов Invoke "отправит" операцию в поток пользовательского интерфейса. Каждый последующий вызов Invoke будет отправляться последовательно, поэтому на самом деле нет необходимости делать какие-либо блокировки.

Вы можете рассмотреть возможность использования BeginInvoke вместо Invoke для предотвращения блокировки рабочего потока, но, опять же, это будет сделано "поочередно", поэтому не нужно беспокоиться о блокировке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...