2013-12-17 2 views
2

WPF 앱이 있으며 화면에 특정 정보를 표시하기 전에 잠자기 상태로 있습니다. 그래서 그것. 1. 버튼을 클릭하십시오.잠자기가 예상대로 작동하지 않습니다.

  1. 슬리핑 1 초.
  2. 레이블을 표시하십시오.
  3. 수면 1 초.
  4. 레이블을 표시하십시오.
  5. 등 등

    private void RunTest() 
    { 
        clearTable(); 
    
        System.Threading.Thread.Sleep(1000); 
    
        this.Cursor = Cursors.Wait; 
    
        Label_OS_Result.Content = operatingSystem; 
        Image_OS.Visibility = Visibility.Visible; 
    
        System.Threading.Thread.Sleep(1000); 
    
        Label_CPU_Result.Content = procName; 
        Image_CPU.Visibility = Visibility.Visible; 
    
        System.Threading.Thread.Sleep(1000); 
    } 
    

그러나 나는 몇 초간 기다려야 할 것 같다 다음 한 번에 모든 것을 표시 내 버튼을 클릭합니다.

무슨 일이야 ??

+0

. DispatcherTimer를 살펴보십시오. – Clemens

+0

제목을 편집했습니다. "[제목에"태그 "가 포함되어 있어야합니까?] (http://meta.stackexchange.com/questions/19190/)"합의가 "아니오, 그렇지 않아야합니다"로 표시되어야합니다. –

답변

1

예상대로 작동합니다.

Thread.Sleep은 지정된 시간 동안 현재 스레드의 실행을 중지합니다. 따라서 이미지의 가시성을 변경하면 프레임 워크에서 가시성을 변경하기 위해 추가 호출을 한 다음 화면에 그려야합니다 (무효화). 이 작업이 완료되기 전에 스레드를 잠자기하면이 작업을 마칠 수있는 충분한 시간이 없습니다. 화면에서 무언가를 그리는 UI 스레드를 단순히 차단하는 것입니다.

Thread.Sleep이 해결책이 아닐 수도 있으므로 DispatcherTimer 또는 BackgroundWorkers를 확인하는 것이 좋습니다.

+0

수정. Sleep은 UI 스레드를 차단합니다. .NET 4.5의 비동기 패턴을 사용할 수 있습니다. 당신이 찾을 수있는 유사한 예를 (http://stackoverflow.com/questions/2565166/net-best-way-to-execute-a-lambda-on-ui-thread-after-a-delay) : 작업 .Factory.StartNew (() => Thread.Sleep (1000)) .ContinueWith ((t) => (...) – dixus

1

GUI를 표시하는 스레드에서 Thead.Sleep()을 원하지 않습니다.

대신 await Task.Delay()을 시도해야합니다. 이는 sleep과 유사하지만 GUI 스레드를 차단하지 않습니다.

레이블에 대한 가시성 변경이 지연되는 동안 모든 렌더링이 계속 수행됩니다.

1

의도 한대로 작동합니다.

예상 한 내용과 다를 수 있지만 여기있는 문제는 귀하의 기대입니다.

대부분의 시각적 컨트롤에서 속성을 사용하여 컨트롤의 모양을 변경하거나 컨트롤 속성 (예 : 데이터)을 내부적으로 조정 한 다음 다시 그리기를 트리거하면 어떻게됩니까? 다시 그리기를 트리거하기 위해 메시지는 일반적으로이 시각적 컨트롤을 소유 한 스레드의 메시지 큐에 게시됩니다.

이 스레드는 일반적으로 단추를 클릭하거나 마우스를 움직이거나 이미지를 변경했기 때문에 게시 된 메시지를 한 번에 하나씩 처리합니다.

그러나, 스레드는 기본적으로이 (의사 코드)와 같은 기록됩니다

while (true) 
{ 
    var message = GetNextMessageFromQueue(); 
    ProcessMessage(message); 
} 

이 루프가 활성화 된 마지막으로, 그것은 당신의 코드를 호출 결국 메시지를 처리하는 일을 시작했다 지금 자고있어.

기본적으로 메시지 펌핑을 계속하기 위해 메시지 펌프 (이 루프를 구현하는 코드의 일반적인 이름)를 가져 와서 페인트 메시지를 처리하면 절전 모드가 해제됩니다.

처리를 다른 스레드 또는 백그라운드에서 "비공개"로 수행하는 비동기 방식으로 분리 할 수 ​​있습니다.

버튼 클릭이나 이와 유사한 방법으로 백그라운드 스레드에서 (또는 다시 다른 비동기식으로) 수행하지 않고 긴 처리를 시작하면 동일한 문제가 발생합니다. GUI가 정지 된 것처럼 보입니다.

그러나이 문제는 매우 일반적이어서 Microsoft는 Windows에서 특수 지원을 구축했습니다. 이전에는 창문이 매달려있는 것 같았습니다. 그러나 이제 메시지 큐가 "가득 차면"Windows가 창을 페이드 아웃하고 캡션이 응답하지 않음을 나타내는 캡션을 붙입니다. 해결책은 아니지만 약간 더 좋습니다.

0

수면 기능이 올바르게 작동합니다.

더 나은 당신이 이렇게하는 타이머를 사용

타이머가 만들어진 무엇
// Declare it in the constructor of the class 
    int level = 0; 
    Timer timer = new Timer 
    timer.Interval = 1000; 
    timer.Tick +=new EventHandler(timer_Tick); 

private void timer_Tick(object sender, EventArgs e) 
{ 
    timer.Stop(); 
    if (level == 0) 
    { 
     Label_OS_Result.Content = operatingSystem; 
     Image_OS.Visibility = Visibility.Visible; 
     ++level; 
    } 
    else if (level == 1) 
    { 
     Label_CPU_Result.Content = procName; 
     Image_CPU.Visibility = Visibility.Visible; 
     ++level; 
    } 
    else if (level > 1) 
    { 
     this.Cursor = Cursors.Default; 
     return; 
    } 
    timer.Start(); 
} 
private void RunTest() 
{ 
    clearTable(); 

    //System.Threading.Thread.Sleep(1000); 
    timer.Start(); 
    this.Cursor = Cursors.Wait; 
} 
+0

실행 해 보았습니까? UI 요소에 액세스 할 수 없어 런타임 예외가 발생합니다. 타이머 틱 이벤트가 UI 스레드가 아닌 백그라운드 스레드에서 호출 됨 –

+0

예, 작동하며 예외가 없습니다. 스레드에서 틱 이벤트를 실행하지 않았으므로 사용할 수 있습니다. –

관련 문제