Диспетчер.BeginInvoke c #, Silverlight - PullRequest
1 голос
/ 16 марта 2011

В Silverlight для маршалинга вызова потока пользовательского интерфейса мы должны использовать this.Dispatcher.BeginInvoke((ThreadStart)delegate(){}).

Мой вопрос: если несколько потоков вызывают функцию, которая делает это, тогда эти вызовы ставятся в очередь и выполняютсяодин за другим?Если да, то могу ли я смело предположить, что, хотя функция вызывается из нескольких потоков, код внутри this.Dispatcher.BeginInvoke((ThreadStart)delegate(){} ); является потокобезопасным?

Ответы [ 4 ]

3 голосов
/ 16 марта 2011

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

Таким образом, нет гарантии безопасности резьбы от Dispatcher.BeginInvoke. При этом гарантируется, что все делегаты будут выполняться в одном и том же потоке (потоке пользовательского интерфейса), поэтому можно предположить, что делегаты не будут работать одновременно. Это не означает, что они по своей природе поточно-ориентированы - это зависит от того, что вы делаете в этих делегатах, - но если вы не вращаетесь или не взаимодействуете с другими потоками из этих делегатов или методов, вызываемых этими делегатами, вы можете предполагать безопасность потоков.

1 голос
/ 16 марта 2011

Ваши фрагменты кода немного вводят в заблуждение из-за использования типа делегата (ThreadStart). Важно знать, что в любой среде STA Threaded существует ровно один поток, который считается потоком «UI». Все объекты пользовательского интерфейса должны быть созданы и взаимодействовать в этом потоке.

Таким образом, Dispatcher используется для нескольких вещей, которые проще всего понять - использовать его из фонового потока, чтобы вернуть то, что вы вызываете, в поток пользовательского интерфейса. Таким образом, то, что вы вставляете туда, не совсем «потокобезопасно», но гарантированно вызывается в потоке пользовательского интерфейса. Если вы поместите все, что делаете, в поток пользовательского интерфейса, он будет вызываться один за другим, а не одновременно.

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

Еще одна важная вещь, которую нужно иметь в виду, это то, что Dispatcher - это очередь с приоритетами. Так что это не чистая очередь в смысле «первым пришел-первым вышел», потому что то, где вы вставлены в очередь, зависит от вашего приоритета, и вполне возможно, что в очередь будет помещено достаточно вещей, чтобы ваш вызванный метод никогда не выполнялся .

0 голосов
/ 16 марта 2011

В общем, да, вы правы, что каждый делегат добавляется в очередь для ожидания обработки потоком Dispatcher.

Я не уверен, есть ли какая-либо текущая или будущая гарантия при заказе вызова делегата из вызовов Dispatcher.BeginInvoke () - но я знаю, что в настоящее время порядок, похоже, сохраняется.1003 *

Несмотря на это - да, можно с уверенностью предположить, что будет только поток Dispatcher (UI) - поэтому несколько делегатов не будут вызываться одновременно.

0 голосов
/ 16 марта 2011

Да, эти звонки помещаются в очередь. Вызовы BeginInvoke являются поточно-ориентированными (вы можете вызывать этот метод из любого потока в любое время), и все вызовы, маршалированные в поток пользовательского интерфейса, выполняются однопоточными. Потому что есть только один поток пользовательского интерфейса. Потому что.

...