Обзор
Существуют ли объяснения для Control.BeginInvoke (), чтобы не выполнять делегат, которому он передан?
Пример кода
Мы приняли следующий шаблон внаши приложения Winforms для безопасного выполнения определенной работы пользовательского интерфейса в потоке пользовательского интерфейса:
private Control hiddenControl = new Control();
private void uiMethod()
{
MethodInvoker uiDelegate = new MethodInvoker(delegate()
{
Logging.writeLine("Start of uiDelegate");
//ui releated operations
childDialog = new ChildDialog();
childDialow.show();
Logging.writeLine("End of uiDelegate");
});
if (hiddenControl.InvokeRequired)
{
Logging.writeLine("Start of InvokeRequired block");
hiddenControl.BeginInvoke(uiDelegate);
Logging.writeLine("End of InvokeRequired block");
}
else
{
uiDelegate();
}
}
Здесь мы явно создаем элемент управления «hiddenControl» для запуска делегатов в потоке пользовательского интерфейса.Мы никогда не вызываем endInvoke, потому что, по-видимому, не требуется для Control.BeginInvoke, и нам никогда не нужно возвращать значение, так как наши методы в любом случае просто манипулируют пользовательским интерфейсом.
Хотя этот шаблон и очень многословный,быть относительно скважиной принятым решением .Однако есть свидетельство , что даже этот шаблон может работать не во всех ситуациях.
Наблюдения
Я не исключаю ошибку приложения и обвиняю WinForms,В конце концов, select, вероятно, не нарушен .Однако я затрудняюсь объяснить, почему делегат, похоже, вообще не баллотируется.
В нашем случае мы иногда наблюдаем, что сообщение журнала «Start of uiDelegate» никогда не выполняется в определенных сценариях потоков, даже если «Начало блока InvokeReqiured» и «Конец блока InvokeRequired» выполняются успешно.
Было очень трудно воспроизвести это поведение, потому что наше приложение поставляется в виде DLL;наши клиенты запускают его в своих собственных приложениях.Поэтому мы не можем дать никаких гарантий того, как или в каком потоке эти методы могут быть вызваны.
Мы исключили голодание потока пользовательского интерфейса, поскольку наблюдается, что пользовательский интерфейс не блокируется.Предположительно, если пользовательский интерфейс обновляется, тогда насос сообщений работает и доступен для извлечения сообщений из очереди сообщений и выполнения их делегатов.
Сводка
Учитывая эту информацию, есть ли что-нибудь, чтомы можем попытаться сделать эти звонки более пуленепробиваемыми?Как упоминалось ранее, мы относительно мало контролируем другие потоки в данном приложении и не контролируем, в каком контексте эти методы вызываются.
Что еще может повлиять на успешное выполнение делегатов в Control.BeginInvoke () илинет?