2010-12-05 3 views
1

다른 스레드에서 일부 컨트롤의 속성을 가져 오려고합니다. 예를 들어.net multithreading winforms

string s = textBox1.Text; 

및 안전하지 않은 스레딩에 대한 예외가 표시됩니다. 경우 은 내가

textBox1.Invoke(new MethodInvoker..blablabla 

처럼, 내가 호출 전화 나에 대한 명확한를 속성을 설정하지만 때 내가 "수"로 무엇을 할 수 있는지?

+0

정말하고 싶습니까? 나쁜 디자인 같아. – CodesInChaos

답변

0

Invoke를 사용하지 않고도 값을 읽을 수 있지만 그렇게하지 않는 것이 좋습니다. 모든 GUI 읽기/쓰기를 메인 스레드로 중앙 집중화하십시오. 작업을 수행 할 수 있도록 필요한 모든 값을 백그라운드 스레드에 전달하십시오. 이 배경 스레드는 GUI에 관해서는 알지 못한다. 입력을 받아서 처리해야하고 GUI에 의해 해석 될 수 있도록 Invoke 메소드를 사용하여 전달 된 결과를 생성해야한다. 이것은 재사용을위한 것입니다. 내일 콘솔 API 나 WPF 같은 다른 GUI로 전환한다고 상상해보십시오. 백그라운드 스레드 코드가 GUI 액세스와 섞여 있으면 쉽게 재사용 할 수 없습니다.

또한 으로 주 스레드에 대한 호출을 수동으로 마샬링 할 필요가 없도록 편리한 이벤트를 제공하는 BackgroundWorker을 살펴볼 수 있습니다.

+0

독서 중이므로 더 안전하지 않습니다. * this * case에서는 문자열이 원자 읽기를 보장하기 때문에 우연히 발생할 수 있습니다. 그러나 일반적으로 첫 번째 행은 나쁜 조언입니다. –

+0

그래서, 예 plz 날 수 있습니다. 나는 텍스트 상자에서 다른 스레드의 텍스트를 가져오고 싶다. 가장 좋은 방법은 무엇입니까? 코드 샘플을 보내주십시오. 내가 이해가 안 돼, 내가 어떻게 설계 할 수 – eba

+0

흠. 비동기 호출에 매개 변수를 전달하는 것과 같은가? – eba

4

당신은 얻을도에 대한 호출 사용해야합니다

string text = null; 
someControl.Invoke((MethodInvoker) delegate { 
    text = someControl.Text; 
}); 

스레드 친화력이 모든 작업에 영향을 미친다; 쓴다. 다른 스레드가 뭔가를 변경하는 중일 수 있습니다. 문자열의 경우 (원자 참조 읽기로 인해) 어느 방향으로 보일 지 모르지만 남용해서는 안됩니다. Invoke를 사용하십시오.

+0

람다 구문을 사용하지 않는 이유는 무엇입니까? '() => {text = someControl.Text; } ' – Richard

+2

@ 리차드 -이 경우 어느 쪽도 훨씬 짧지 않으므로 리더가 VS2005를 사용하는 경우에도 대리인 버전이 작동합니다. –

2

가능한 경우 백그라운드 스레드를 시작하기 전에 GUI 스레드에서 TextBox 값을 읽고이 값을 매개 변수로 백그라운드 스레드에 보냅니다.

일반적으로 UI와 비즈니스 논리를 구분하는 것이 바람직하며 UI 구성 요소를 인식하지 못하는 방식으로 백그라운드 작업을 설계하면 도움이됩니다.

결국 배경 스레드에서 UI 값에 액세스해야한다면 Invoke 또는 BeginInvoke을 사용하여 TextBox에서 값을 가져올 수 있습니다.