Почему InvokeRequired предпочтительнее, чем WindowsFormsSynchronizationContext?

Каждый раз, когда новичок спрашивает что-то вроде: Как обновить графический интерфейс из другого потока на C #? , ответ довольно прост:

if (foo.InvokeRequired)
{
    foo.BeginInvoke(...)
} else {
    ...
}

Но действительно ли это хорошо использовать ? Сразу после того, как поток без графического интерфейса выполнит foo.InvokeRequired , состояние foo может измениться. Например, если мы закроем форму сразу после foo.InvokeRequired , но до foo.BeginInvoke , вызов foo.BeginInvoke приведет к InvalidOperationException ]: Invoke или BeginInvoke нельзя вызвать для элемента управления, пока не будет создан дескриптор окна. Этого не произойдет, если мы закроем форму перед вызовом InvokeRequired , потому что это будет false даже при вызове из потока без графического интерфейса.

Другой пример. Допустим, foo - это TextBox . Если вы закроете форму и после этого поток без графического интерфейса выполнит foo.InvokeRequired (что неверно, потому что форма закрыта) и foo.AppendText , это приведет к ObjectDisposedException .

Напротив, на мой взгляд, использование WindowsFormsSynchronizationContext намного проще - отправка обратного вызова с использованием Post будет происходить, только если поток все еще существует, а синхронные вызовы с использованием Отправить бросает InvalidAsynchronousStateException , если поток больше не существует.

Разве не проще использовать WindowsFormsSynchronizationContext ? Я что-то пропустил? Почему мне следует использовать шаблон InvokeRequired-BeginInvoke, если он? не совсем потокобезопасный? Как вы думаете, что лучше?

7
задан Community 23 May 2017 в 12:02
поделиться