2010-03-27 2 views
2

작업을 수행하고 몇 초 동안 바쁜 GUI (C#, WinForms)가 있다고 가정합니다.바쁜 GUI를 제어하는 ​​모범 사례

//Generic delegates 
private delegate void SetControlValue<T>(T newValue); 

//... 
public void SetStatusLabelMessage(string message) 
{ 
    if (StatusLabel.InvokeRequired) 
     StatusLabel.BeginInvoke(new SetControlValue<string>(SetStatusLabelMessage, object[] { message }); 
    else 
     StatusLabel.Text = message; 
} 

봤는데 : 그것은 아직도 계속 액세스 할 필요가 버튼 등이 변경됩니다 라벨, 진행 바, 바쁜 때 GUI를 변경하는 것은 현재이 방법을 사용하고

이있을 것이다 스타일을 벗어나는 것처럼 이것을 사용하면, 아직 나는 이것이 적절하다는 것을 확신하지 못합니다. 델리게이트를 만들고 재사용하면 모든 것을 깨끗하게 처리 할 수 ​​있지만 (적어도 나를 위해), 나는 몬스터를 만들지 않는다는 것을 알아야한다. ...

답변

6

또 다른 대안은 BackgroundWorker을 사용하고 GUI를 업데이트해야 할 때 ReportProgress을 사용하는 것입니다. 이렇게하면 Invoke가 처리되므로 걱정할 필요가 없습니다.

+0

나는 프로그램에서 사용 된 BackgroundWorkers 및 다른 스레딩을 조율하는데 힘든 시간을 보냈습니다. 잘 여행 한 신사 프로그래머로서, 더 자주 볼 수 있습니까? BackgroundWorker 또는 Invoke를 통해 제어 하시겠습니까? – MPelletier

+0

@MPelletier : 이런 종류의 작업을 수행하는 BackgroundWorker - 장기 실행 작업이 있으며 GUI 응답을 유지해야하며 진행률 표시 줄을 표시해야합니다. 바로 BackgroundWorker가 설계된 것입니다. –

+0

"백그라운드 스레드에서 UI를 업데이트하는 가장 좋은 방법은 무엇입니까?" 이 대답은 그 질문을 실제로 다루지 않습니다. –

1

그것은 나에게 잘 보인다. 여러분이 잘 테스트 한 클래스에 그런 종류의 것을 캡슐화한다면, 아무런 문제가 없어야합니다.

+0

: 또한, 대신 별도의 대리자를 선언, 당신은 당신의 코드를 단순화하기 위해 MethodInvoker를 사용할 수 있습니까? 나는 폼 클래스에서 최대한 많은 코드를 섞어서 사용하지 않는다. 폼을 컨트롤한다면, 폼 클래스에서 * 유지하는 습관이있다. – MPelletier

+1

@MPelletier : 저는 이미 구현 된 UI 구현 코드를 응용 프로그램과 비즈니스 논리에서 제외하고, 이는 이미 자체 클래스로 분리되어 있어야합니다. 그래서 실제로 폼 클래스에 그 것들을 넣는 것이 좋습니다. –

2

여기서 가장 좋은 방법은 BackgroundWorker를 사용하여 장기 실행 작업을 실행하는 것입니다. 이 목적을 위해 WinForms 전용으로 특별히 설정된 스레딩 클래스입니다. 작업을 보내고 취소 한 다음 메시지를 WinForm 스레드로 보내서 상태를 업데이트 할 수 있습니다. 기본적으로 BackgroundWorker를 사용하면 GUI가 자유롭고 활성 상태로 유지됩니다.

+0

하지만 그는 이미 BackgroundWorker와는 다른 클래스를 사용하고 있지만 정확히이 작업을 수행하고 있습니다. –

+1

그는 "모범 사례"를 요구했습니다. BackgroundWorker는 "모범 사례"입니다. –

2

다른 사람들은 귀하의 작업을 실행하기 위해 BackgroundWorker를 사용한다고 언급했습니다.

어쨌든 BeginInvoke 대신 Invoke을 사용하는 것이 좋지만, 백그라운드 스레드에서 UI를 업데이트하는 가장 좋은 방법은 무엇인지 궁금하신가요? 폼 클래스에 반대 뜻 이죠, "자신의 클래스로"으로

StatusLabel.Invoke(new MethodInvoker(delegate() { /* Update control here */ })); 
+0

BackgroundWorker를 사용하지 않습니다. BGW가 단 하나의 선형 함수를 호출하는 경우, 그것을 할 것이지만, 백그라운드 함수가 ThreadPool을 사용하는 프로그램에서 주저합니다. 그 수준에서, 나는 불필요하게 구조물을 겹쳐 쌓고있는 것처럼 느낍니다. Invoke/BeginInvoke를 주셔서 감사합니다. 차이점을 더 잘 이해하기 위해 마음을 새롭게해야합니다. MethodInvoker도 괜찮아 보입니다! – MPelletier

+0

문제 없습니다. 이 질문은 귀하의 질문에 대한 답을 찾거나 도움이 될만한 것이 있습니까? –