2012-02-07 2 views
0

저는 C# 및 .NET 4.0을 사용하고 있습니다.시스템 메시지 흐름을 멈추지 않고 프론트 엔드가 긴 프로세스를 마칠 때까지 대기해야합니다.

내 프로그램은 프런트 엔드와 백 엔드로 구성됩니다. 백엔드는 시스템 시작시 자동으로 시작되는 Windows 서비스로 실행됩니다. 프런트 엔드는 사용자가 응용 프로그램을 사용할 준비가되었을 때 시작할 WPF 응용 프로그램입니다.

시작 프로세스의 일부로 프런트 엔드는 백 엔드와 통신을 설정해야합니다. 이것은 XMPP를 사용하여 이루어지며 잘 작동합니다. 통신을 수행하는 코드에는 WaitHandle을 반환하는 BeginStart 메서드가 있습니다. try-catch 내부에서 BeginStart를 호출하고 WaitHandle을 얻은 다음 Waithandle의 WaitOne (TimeSpan) 메서드를 호출합니다. 이 시점에서 프로그램에 스플래시 화면이 표시됩니다. 그리고 이러한 호출은 프론트 엔드 스레드에서 수행됩니다.

괜찮 으면 좋겠지 만 WaitOne 호출이 실행되는 동안 다른 창을 클릭하면 아무 효과가 없습니다. 본질적으로 모든 Windows 메시지 트래픽은이 WaitHandle이 반환 될 때까지 대기하지 않습니다.

다른 스레드에서 BeginStart 및 WaitOne 호출을해야한다고 생각합니다. WaitOne 호출이 성공적으로 반환되지 않으면 (시간 제한 없음) 프로그램이 종료되고 사용자 인터페이스가 표시되지 않으므로 프런트 엔드에서 WaitOne이 반환되기를 기다리는 것이 필요합니다. 다른 프로그램이 Windows 메시지를 처리 ​​할 수있게하면됩니다.

어떻게하면됩니까? WPF에는 Application.DoEvents 메서드가 없습니다.

토니

편집 : 내가 좀 더 정보를 제공하는 경우가 도움이 될 수 있습니다처럼

것 같습니다.

내 WPF 응용 프로그램은이 제품의 사용자 인터페이스이며 전체 제품의 절반 만 구성합니다. 나머지 절반은 동일한 PC에서 Windows 서비스로 실행되며이를 백엔드라고 부릅니다. 백엔드에서 진행되는 작업은 XMPP를 사용하여 연결을 수신하는 것을 제외하고는 중요하지 않습니다.

사용자 인터페이스 (또는 프런트 엔드)가 시작되면 XMPP를 사용하여 백엔드와 통신을 설정해야합니다. 이 작업은 정상적으로 최대 두 번째 또는 두 번만 수행해야합니다. 그러나 사용자가 프런트 엔드를 시작할 때 잘못된 것이 있거나 백 엔드가 다운 될 수 있습니다. 프론트 엔드가 무한정 기다리는 것을 원하지 않습니다. 합리적인 시간이 지나면 시간 초과되어 오류 메시지를 표시하고 죽을 필요가 있습니다.

통신을 설정하려면 내가 시작하는 별도의 스레드로 실행되는 모듈이 있습니다. WaitHandle을 반환하는 BeginStart 메서드를 호출합니다. WaitHandle을 기다렸다가 TimeSpan을 내 제한 시간으로 설정합니다. 스 니펫은 다음과 같습니다.

try { 
    WaitHandle handle = BackgroundProcess.BeginStart(); 
    if (!handle.WaitOne(Timeout)) { 
     // Something went wrong; Notify user here 
     return false; 
    } 

    // Make sure that the Background Process has started all of it's internal modules 
    bool allAreRunning; 
    Stopwatch timer = new Stopwatch(); 
    timer.Reset(); timer.Start(); 
    do { 
     allAreRunning = true; 
     foreach (Module module in BackgroundProcess.Modules) { 
      if (module.State != Module.States.Running) { 
       allAreRunning = false; 
       break; 
      } 
     } 

     if (!allAreRunning) { 
      // I hate this loop, but I can't think of a better way to do this 
      Thread.Sleep(1000); 
     } 

    } while (!allAreRunning && timer.ElapsedMilliseconds <= Timeout.TotalMilliseconds); 

    timer.Stop(); 

    if (!allAreRunning) { 
     // Something went wrong; Notify user here 
     return false; 
    } 

    // Other initialization done here 

} catch (Exception ex) { 
    // Something went wrong; Notify user here 
    return false; 
} 

이 문제를 테스트하려면 백엔드가 작동 중지 된 상태에서 디버거에서 프로그램을 실행해야합니다. 열려있는 창을 클릭하여 전환 할 수 있습니다. 내가 할 수없는 일은 바탕 화면을 클릭하는 것입니다. WaitHandle.WaitOne() 호출은 백그라운드 프로세스가 실행을 시작하고 연결이 설정 될 때까지 기다리지 않고 반환하므로 매우 신속하게 반환됩니다. 대부분의 제한 시간 동안 실행되는 do-while 루프입니다.

사용자가 프로그램을 열뿐만 아니라 바탕 화면을 클릭하여 전환 할 수 있도록이 코드를 다시 작성해야합니다. 나는 그것을 어떻게 작동시키는 지 모릅니다.

토니

+0

한 프로그램이 시스템의 다른 모든 프로그램을 차단해서는 안

. 코드 스 니펫을 게시 할 수 있습니까? –

답변

0

이 시작 논리를 코딩하는 더 좋은 방법을 발견했습니다. 그러나 코드는 내부 코드의 아키텍처에 의존합니다.

코드 스 니펫에서 do-while 루프를 제거하고 더 나은 코드로 바꿀 수있었습니다. 이제 코드는 모든 Module 객체를 반복하고 실행 상태 인 WaitHandle을 쿼리합니다. 이들은 List 컬렉션에 추가됩니다. 루프가 완료되면 List를 배열로 변환하고 .ToArray()를 호출 한 다음 WaitHandle.WaitAll 메서드를 호출합니다.

코드는 지금과 같은 :

try { 
    WaitHandle handle = BackgroundProcess.BeginStart(); 
    if (!handle.WaitOne(Timeout)) { 
     . . . 
     return false; 
    } 

    List<WaitHandle> waitHandles = new List<WaitHandle>(); 
    foreach (Module module in BackgroundProcess.Transit.SubModules) { 
     WaitHandle waitHandle = module.GetWaitHandleForState(Module.States.Running); 
     waitHandles.Add(waitHandle); 
    } 

    if (!WaitHandle.WaitAll(waitHandles.ToArray(), Timeout)) { 
     . . . 
     return false; 
    } 

    // If we get here, everything is communicating properly. 
    . . . 

} catch (Exception ex) { 
    . . . 
    return false; 
} 

return true; 

감사 토니

1

당신은 BackgroundWorker에 전화를 이동하고 WorkerCompleted 이벤트 완성 된로드를 잡을 수 있습니다. ProgressChanged 이벤트를 통해 UI의 진행률을 업데이트 할 수도 있습니다.

+0

시작 화면이 표시되는 동안 프로세스가 실행 중입니다. 업데이트 할 UI가 없습니다. 그리고 저는 백그라운드 프로세스가 응용 프로그램의 일부인 Windows 서비스와의 연결을 설정하기를 기다리고 있습니다. 진행할 것이 없습니다. 내 원래의 질문에 대한 편집을 참조하십시오. –

+0

어떻게 스레드가 돌아 오기를 기다리고 계십니까? 주 스레드가 자식 스레드가 끝날 때까지 기다리는 코드를 게시 할 수 있습니까? 메인 스레드가 계속 실행되는 방식으로 작업을 수행 할 가능성이 있습니다. – rie819

+0

방금 ​​ASP.NET에서이 작업을 수행하려는 것으로 나타났습니다. ASP.NET에서 스레드하지 마십시오. 웹 페이지에서 웹 서비스 호출을 할 수는 있지만 ASP.NET 응용 프로그램을 멀티 스레드하는 것은 좋지 않습니다. – rie819

관련 문제