2

작은 .NET (Windows Forms) 응용 프로그램을 작성하고 있지만 다중 스레드 권한을 얻을 수없는 것 같습니다.처리하는 동안 제어 업데이트를 처리하는 방법?

응용 프로그램에는 매우 간단한 논리가 있습니다. 입력 할 매개 변수가있는 기본 폼과 처리를 시작하는 버튼 및 진행률 막대가 표시됩니다. 사용자가 버튼을 클릭 할 때 처리가 시작되고 프로그램이 실행되는 동안 진행 막대가 업데이트되어야하며 경고/정보를 표시하기 위해 처리 중에 일부 MessageBox이 팝업 될 수 있으며 처리가 끝나면 다른 MessageBox이 결과를 팝업합니다. 매우 간단하지만 컨트롤 업데이트를 올바르게 처리 할 수있는 방법을 찾지 못하는 것 같습니다.

먼저 Button_Clicked 이벤트에서 모든 처리를 수행하는 간단한 경로를 시도했습니다. 이것은 잘 진행되지 않았지만 작동했지만 양식이 처리되는 동안 완전히 응답하지 않게되어 사용자 클릭에 전혀 신경을 쓰지 않았습니다. 나는 실제로 이벤트를 처리하고있어서 다른 것들을 처리하지 않으므로 이것이라고 가정했다. 그래서 나는 멀티 스레딩을했다.

버튼 처리 이벤트에서 나는 새 Thread을 시작하여 처리를 수행 한 다음 Thread.Join을 호출했습니다. MSDN 문서에 따르면 Thread.Join : "표준 COM 및 SendMessage 펌핑을 계속 수행하면서 스레드가 종료 될 때까지 호출 스레드를 차단합니다."(http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx). 그러나 이것이 사실 인 것처럼 보이지 않습니다. Thread.Join을 호출 한 후 스레드가 종료 될 때까지 양식이 다시 응답하지 않게되었습니다. 왜 이런거야? Join 아이디어를 버리고 즉시 처리 기능 (사용자가 동시에 두 개 이상의 처리를 시작하지 못하도록 양식의 단추를 사용 불가능하게 함)에서 즉시 복귀했지만 다른 문제를 만났습니다. 진행 상황을 업데이트하려고 할 때 예외가 발생하기 시작했습니다. 런타임에서 런타임에 소유자가 아닌 스레드에서 컨트롤을 호출하는 것에 대해 불만을 표시했습니다.

그래서 나는 마침내 BackgroundWorker 갔다 : 나는 폼에 하나를 추가의 RunWorkerAsync() 방법에 전화 (크로스 스레드 제어 업데이트 문제를 방지하기 위해)을 ProgressChanged 이벤트가 발생하고 기본 형태를 처리 할 수 ​​ ReportProgress()을 사용했다. 마침내 진행률 막대를 업데이트 할 수있었습니다 ...하지만 이제는 완전히 비동기 적입니다. 작업자 스레드가 ReportProgress() (심지어 1 초!)를 호출 한 후 진행률 막대가 실제로 임의의 간격으로 업데이트되고 이로 인해 특히보기 흉한 시각 효과가 나타납니다 . 두 가지 예 : 내가 현재의 처리 단계에 대한 몇 가지 메시지를 표시하기 위해 작업자 스레드에서 ReportProgress() 다음 MessageBox.Show()를 호출 할 경우

  • , 나는 메시지 박스가 팝업 후 발전 진행률 표시 줄을 볼 수 있습니다.
  • 나는 MessageBox을 결과로 팝업하는 RunWorkerCompleted 이벤트가 있으며, 진행 막대가 여전히 마지막 단계 인을 채우는 동안 화면 에 팝업이 표시됩니다.

무엇이 여기에 있습니까?

+0

그것은 당신은 아무것도 놓친없는 한 것 같은 것을 사용하는 것이 좋습니다. 메시지 함이 필요합니까? 그것을 제거하면, 그것도 추함을 줄일 수 있습니까? 처리하면서 마지막에 모두 – Kangkan

+0

예, 응용 프로그램 로직은 그들을 필요로한다. 물론 거기에 일부'에 Thread.sleep()'넣을 수 있지만, 이것은 정말 추한 해킹처럼 보인다 ... – Massimo

답변

0

IMHO는 WinForm (및 WPF) 응용 프로그램에서 비동기를 처리하는 데 가장 좋은 방법은 Reactive Extensions입니다. 통과 할 곡선의 비트이지만 일단 당신이 그것을 얻으면 당신은 돌아 가지 않을 것입니다.

0

Application.DoEvents()를 추가하여 필요한 UI를 업데이트하십시오.

0

그럼 당신은 꽤 많은 것들을 시도했습니다. 여기에 몇 가지 팁이 있습니다. 아마도 당신에게 옳은 대답은 아니지만, 당신을 도울 수 있습니다.

"다른 스레드에서 제어를 업데이트하는 중"문제를 극복하려면 Invoke 또는 BeingInvoke 명령을 컨트롤에 사용할 수 있습니다 (이 경우 extension method을 사용합니다). 이 모달이며 업데이트에서 차단 UI를하기 때문에, MessageBox에 그냥 문제로 고통을 추가하여 - 제외하고, 내가 Kangkan의 댓글이 합법적이라고 생각

. 당신이 절대적으로 계속하기 전에 사용자의 입력을 필요합니까 - 당신은 메시지 박스가 적절하다고 확신? 또는 당신은 그 (것)들에게 알릴 필요가 있는가? 후자의 경우, 당신은 더 많은 상태 표시 줄, 또는 당신에 유래 여기에 얻을 수있는 시스템 메시지 (그들은 모든 경고이라면 상상!)

관련 문제