2012-04-24 4 views
2

В асинхронном вызове OnMsgRecieved, если я назначаю значение непосредственно элементу управления, он не работает. Затем я узнал, что это связано с тем, что поток небезопасен, и я получил следующий код для решения проблемы. Теперь он работает. Но я не уверен, что он делает практически. Может ли кто-нибудь заставить меня полностью его понять? Код: - УправлениеЧто именно происходит с потоками окон?

 public void listener_OnMsgRecieved(string aResponse) 
    { 
     ShowResponseMessage(aResponse); 
    } 

    public void ShowResponseMessage(string aResponse) 
    { 
     // InvokeRequired required compares the thread ID of the 
     // calling thread to the thread ID of the creating thread. 
     // If these threads are different, it returns true. 
     if (this.listBox.InvokeRequired) 
     { 
      SetTextCallback d = new SetTextCallback(ShowResponseMessage); 
      this.Invoke(d, new object[] { aResponse }); 
     } 
     else 
     { 
      this.listBox.Items.Add(aResponse); 
      label.Text = "Response received from Server :"; 
     } 
    } 

ответ

1

Когда ShowResponseMessage вызывается в другом потоке от того пользовательского интерфейса, то InvokeRequired вернется true, то вы используете Control.Invoke, чтобы отправить сообщение в очередь сообщений Windows.

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

Фокус в том, что делегат не вызывается непосредственно в не вызывающем UI потоке вызовов. Используя сообщения Windows, команда для выполнения делегата передается в поток пользовательского интерфейса, который затем выполняет делегат в ответ на сообщение. «Control.Invoke» использует Windows [SendMessage][1], Control.BeginInvoke использует API-интерфейс [PostMessage][2] Win32 для облегчения прохождения сообщения.

+0

Есть ли что-то, что связано с контекстом синхронизации? – userGS

+0

Спасибо, практическое объяснение! –

0

UI не может быть обновление/изменено с любого другого потока, чем основной нити/нить была создана.

В вашем случае проверка InvokeRequired проверяет, является ли поток, который хочет изменить элемент управления, создающим потоком, и если он не передает обратный вызов основному потоку/создателю.

Посмотри How to: Make Thread-Safe Calls to Windows Forms Controls

Если вы используете многопоточность для улучшения производительности вашего Windows, Forms приложений, вы должны убедиться, что вы делаете вызовы по управлению в поточно-образом.

Доступ к элементам управления Windows Forms по существу не является потокобезопасным. Если у вас есть два или более потока, управляющих состоянием элемента управления, то можно отключить управление в несогласованном состоянии . Другие возможны связанные с потоком ошибки, такие как условия гонки и взаимоблокировки. Важно убедиться, что доступ к вашим элементам управления выполняется поточно-безопасным способом.

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

Смежные вопросы