2010-02-18 4 views
4

다른 사람의 코드를 조사 중이며 멀티 스레딩과 관련하여 많은 경험이 없습니다. 나는이 코드 줄 건너 온 : btnCalibrate.PerformClick();여기에서 BeginInvoke를 사용하는 이유는 무엇입니까?

감사합니다 귀하의 답변 : 그냥이 일을했을 때 이렇게하는 이유

BeginInvoke((MethodInvoker)delegate() { btnCalibrate.PerformClick(); });

가 궁금했다.

답변

5

GUI에서 단추를 만든 스레드와 다른 스레드에서이 코드를 실행하면 예외가 발생하기 때문입니다. 배경 스레드는 GUI가 스레드 안전하지 않기 때문에 GUI에서 직접 메서드를 호출 할 수 없습니다.

물론 이것은 BeginInvoke을 사용하는 합리적인 이유입니다! 그러나 저자가 그와 같은 방식으로 다른 예를 보았고 모든 경우에 반드시 필요하다고 가정했기 때문에 정당한 이유없이 마법이나 마법을 포함하는 코드를 찾는 것은 드문 일이 아닙니다. 함께 작업하는 코드가 단일 스레드 인 경우에는 필요하지 않습니다.

특히 Windows Forms 자체는 단호하게 단일 스레드입니다. 모든 창과 컨트롤에 대한 모든 작업은 동일한 스레드에서 발생하며 모든 이벤트는 동일한 스레드에서 실행됩니다. 하나의 GUI 스레드의 사용은 스레드에서 계속 실행되고 대기열에서 메시지를 읽는 메시지 루프를 통해 분할됩니다. BeginInvoke의 목적은 궁극적으로 해당 대기열에 메시지를 게시하여 "잠시 시간이되면 코드 조각을 실행하십시오."라고 말합니다.

+0

저의 허락을 용서하되 btnCalibrate는 "Form1"에 존재하며 위의 코드는 "Form1"에도 있습니다. 위 코드는 Form1.cs에서'void wm_OnWiimoteChanged'라는 함수에 존재하고'btnCalibrate_performClick'은 같은 파일에 존재합니다. 그렇다면 "다른 스레드"는 어디에서 왔습니까? – Aishwar

+0

이 주제에 관해 나에게 교육 할 기사를 제안 할 수 있다면, 그 점을 높이 평가할 것입니다! :) – Aishwar

+1

@ aip.cd.aish :이 기사가 마음에 듭니다. http://msdn.microsoft.com/en-us/magazine/cc188732.aspx 아 ... 추억 ... – codekaizen

1

@Earwicker를 약간 확장하면 Control.BeginInvoke는 한 스레드에서 Control 인스턴스를 소유 한 스레드로 호출을 전송하는 방법입니다. 백그라운드에서는 PostMessage이라는 Win32 함수를 통해 Win32 메시지를 사용하여 소유 스레드에서 PerformClick 메서드 호출을 마샬링합니다. 이것은 Win32 Windows와 확장 WinForms 컨트롤, 일반적으로 GUI를 실행하는 단일 스레드 인 스레드를 만든 스레드에서만 안전하게 액세스 할 수 있기 때문에 필요합니다.

이유 BeginInvoke는 대 Invoke 후자는 내부적으로 SendMessage를 사용하는 반면 이전 사용 PostMessage하고, 즉시 반환하기 때문에, 그리고 GUI 스레드에서 응답을 PostMessage을 기다립니다 기다릴 필요가 사용됩니다. 이렇게하면 통화를하는 스레드가 지연되거나 응용 프로그램이 잠길 수 있으므로 여기에서 BeginInvoke을 선택하는 것이 좋습니다.

+0

Invoke는 SendMessage를 사용하지 않습니다. PostMessage도 사용하지만 리턴하기 전에 결과를 기다립니다. – Andy

+0

@Andy - 좋아요. 실제로, BeginInvoke/Invoke를 PostMessage/SendMessage와 비슷한 방식으로 사용하는 동안 PostMessage/Wait와 비교하여 SendMessage (메시지 대기열을 점프하고 WinProc로 바로 이동) 동작이 달라 지므로이 구분 작업을 보존 할 수 있습니다. 내 용도에 대한 실질적인 차이가 없었기 때문에 나는 눈치 채지 못했습니다. – codekaizen

관련 문제