Будут ли несколько вызовов Control.BeginInvoke/Invoke выполняться по порядку?

Мне нужно знать, будут ли вызовы Control.BeginInvoke и Control.Invoke выполняться в том порядке, в котором они вызываются.

У меня есть следующий сценарий:

  1. Поток пользовательского интерфейса заблокирован
  2. Поток WCF вызывает Control.BeginInvoke
  3. Поток WCF вызывает Control.Invoke (или, возможно, снова BeginInvoke)
  4. Поток пользовательского интерфейса разблокирован
  5. ??

Порядок выполнения шагов 1-4 гарантированно соответствует показанному порядку (технически порядок не гарантируется таким, но вопрос, который у меня есть, актуален только в том случае, если порядок такой, как показано).

У меня есть вопрос: есть ли шанс, что вызов Invoke/BeginInvoke на шаге 3 будет выполнен до вызова BeginInvoke на шаге 2?

Кроме того, пожалуйста, не комментируйте блокировку потока пользовательского интерфейса.


person cornergraf    schedule 10.12.2009    source источник


Ответы (4)


В вашем случае шаг 2 всегда будет выполняться перед шагом 3. BeginInvoke в потоке пользовательского интерфейса будет выполняться в том порядке, в котором он был поставлен в очередь.

Поток пользовательского интерфейса на самом деле является насосом сообщений, он имеет единую очередь сообщений, которую использует только один поток, поэтому гарантируется, что рабочие элементы будут выполняться в том порядке, в котором они были поставлены в очередь.

Именно с Delegate.BeginInvoke порядок выполнения может быть непоследовательным.

person Jeff Cyr    schedule 10.12.2009
comment
Таким образом, комментарий о том, что синхронные вызовы Invoke могут выполняться до асинхронного вызова BeginInvoke, не применяется для Control.BeginInvoke, но применим для Delegate.BeginInvoke? Можете ли вы дать мне ссылку, которая объясняет это? - person cornergraf; 10.12.2009
comment
ВАШЕ утверждение верно. Я добавил краткое объяснение насоса сообщений пользовательского интерфейса в ответ, как ни странно, я не могу найти официальный источник, в котором говорится об этом. - person Jeff Cyr; 10.12.2009
comment
Хорошо спасибо. Я знаю о MessagePump в целом, но я думал, что вызовы BeginInvoke/Invoke потенциально могут иметь особое поведение по какой-либо причине, и я хотел быть уверенным. - person cornergraf; 10.12.2009
comment
На шаге 1 пользовательский интерфейс считается заблокированным. Таким образом, если поток WCF вызывает вызов потока пользовательского интерфейса (через BeginInvoke), он не может быть выполнен до тех пор, пока поток пользовательского интерфейса не будет разблокирован. Я ошибся ? - person Laurent Etiemble; 10.12.2009
comment
Ты прав. Вопрос в том, что происходит после того, как поток пользовательского интерфейса снова разблокируется, какой из двух вызовов BeginInvoke/Invok выполняется первым. - person cornergraf; 10.12.2009
comment
Я только что проверил это и обнаружил, что этот ответ неверен (.NET 3.5, если это имеет значение). Вызовы Invoke могут выполняться до предыдущих вызовов BeginInvoke. - person mafu; 09.05.2010
comment
В разделе «Примечания» статьи BeginInvoke MSDN говорится, что если несколько вызовов BeginInvoke выполняются с одним и тем же DispatcherPriority, они будут выполняться в том порядке, в котором были сделаны вызовы. msdn.microsoft.com/en-us/library /ms591206(v=vs.110).aspx - person W55tKQbuRu28Q4xv; 03.09.2014

Вызовы BeginInvoke ставятся в очередь в потоке назначения (так как они отправляются в порядке поступления).

Синхронные вызовы в потоке WCF (шаг 3) могут выполняться до асинхронных вызовов (шаг 2), сделанных из этого потока.

person Laurent Etiemble    schedule 10.12.2009
comment
Хорошо, большое спасибо. У вас случайно нет источника этого утверждения? Я пытался найти что-то определенное в гугле, но пока безуспешно. - person cornergraf; 10.12.2009

Недостаточно информации, чтобы дать вам хороший ответ. Поток пользовательского интерфейса заблокирован, поэтому шаги 2 и 3 должны выполняться в другом потоке. Если между ними нет синхронизации, то как мы можем узнать какой-либо порядок?

Thread 1        Thread 2                       Thread 3         Thread 4
Block UI        Calls BeginInvoke              
Unblock UI      Calls Invoke or BeginInvoke    BeginInvoke runs  BeginInvoke runs

У вас происходит много параллелизма, но из того, что вы описали, мы не можем сказать вам, какие возможные порядки произойдут, кроме как сказать: «Что угодно». Мы даже не можем сказать вам, что вызовы BeginInvoke не будут происходить до того, как поток пользовательского интерфейса будет заблокирован или после того, как поток пользовательского интерфейса будет разблокирован.

person Greg D    schedule 10.12.2009
comment
Ну, порядок шагов 1-4 гарантированно будет именно в таком порядке. Вопрос только в том, будет ли это также гарантировать порядок выполнения вызовов BeginInvoke/Invoke на шагах 3 и 4. Я обновляю вопрос, чтобы сделать это более ясным. - person cornergraf; 10.12.2009
comment
Аааа, редактирование, в котором говорится, что это Control.BeginInvoke и Control.Invoke, сильно меняется. Рад, что кто-то смог прикрыть это для вас. :) - person Greg D; 10.12.2009
comment
Да, и я только что снова понял, насколько человек склонен принимать определенную информацию как должное, когда обсуждает ее с другими. В будущем постараюсь быть более точным. Спасибо за ваш ответ. - person cornergraf; 10.12.2009

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

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

person rui    schedule 10.12.2009
comment
на самом деле, шаги 3 и 4 можно поменять местами, но если это так, я знаю, что (очевидно) шаг 2 будет выполняться первым. Поэтому мой вопрос актуален только в том случае, если порядок исполнения точно такой, как представлен, поэтому я так его сформулировал. - person cornergraf; 10.12.2009