2012-02-16 3 views
1

Silverlight 콜백에서 여러 UI 업데이트를 어떻게 수행합니까?Silverlight에서 여러 비동기 UI 업데이트

예를 들어 사용자가 버튼을 클릭하고 UI를 변경 한 다음 작업을 수행 한 다음 다시 변경하고 싶습니다. 대신 사용자가 버튼을 클릭하면 콜백이 배경과 모든 UI 변경 사항이 눈앞에 깜박입니다.

에서 MainPage.xaml :

<Grid x:Name="LayoutRoot" Background="White" > 
<TextBlock Height="23" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top"/> 
<Button Click="button1_Click" Content="Button" Height="23" Name="button1" Width="75" /> 
</Grid> 

MainPage.xaml.cs를 :

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    textBlock1.Text = "1"; 
    // also tried Thread.Sleep(5000); 
    Dispatcher.BeginInvoke(() => Thread.Sleep(5000)); 
    textBlock1.Text = "2"; 
} 
+0

작업이 완료되는 동안 스레드를 휴면 상태로 전환하는 대신 작업 완료 후 이벤트가 시작되도록 할 수 있습니다. 그러면 해당 이벤트의 수신자가 두 번째 UI 변경을 수행합니다. –

+0

@iimpact 수면 통화는 작업을위한 것입니다. 질문은 수면 호출 전에 첫 번째 UI 업데이트가 발생하지 않는 이유는 무엇입니까? – jordanpg

답변

0

실버 라이트 UI 스레드에서 렌더링 및 로직 처리하는 작업 항목의 대기열을 사용하여 사용해야하는 이유 여기입니다. 귀하의 로직도 UI 스레드 (button_Click 핸들러)에서 실행되기 때문에 렌더러는 메소드 실행이 끝나고 내부 메시지 루프가 화면을 그리기 전까지 스크린을 그릴 기회를 얻지 못합니다.

BeginInvoke은 UI 스레드에서 즉시 실행되도록 Silverlight 작업 큐에 함수를 저장하고 즉시 반환합니다. 이 아마 같은 것입니다 주문 실버 프로세스 :

  • 사용자는
  • 실버 라이트는 클릭 이벤트를보고 작업 큐에 새로운 액션을 배치 button_Click을 (호출 작업 큐에 클릭 이벤트를 배치, 버튼을 클릭)
  • 프로세스 오초
  • 의 UI 스레드를 일시 중지, 아마 당신의 Thread.Sleep 행동을하다 다음 작업 대기열 항목
  • 마지막으로 실버 라이트는 화면
그림 주위에 도착 다음 작업을 수행하는 새로운 스레드를 시작한다 무엇을 원하는

, 다시 UI 스레드에 BeginInvoke:

var thread = new Thread(() => { 
    Thread.Sleep(5000); 
    Dispatcher.BeginInvoke(() => { 
    // update UI 
    textBox.Text = "2"; 
    }); 
}); 

textBox.Text = "1"; 
thread.Start(); 

내가 추가해야합니다 실버 라이트 5에 특정 작업을 수행 할 수있는 구성 스레드를 추가하는 애니메이션 재생과 같은 UI 스레드를 차단하지 않고 UI를 업데이트하고 가능한 경우 GPU 가속 렌더링을 수행합니다.

+0

감사합니다. 왜 나는 다음과 같이 업데이트 할 수 없습니까? {tb1.Text = "1"; UpdateLayout(); Thread.Sleep (1000); tb2.Text = "2"; }? – jordanpg

+0

'UpdateLayout'은 레이아웃 프로세스의 [measure and arrange] (http://msdn.microsoft.com/en-us/library/cc645025%28v=VS.95%29.aspx) 단계 만 수행합니다. 그림은 여전히 ​​다른 모든 작업과 마찬가지로 작업 대기열을 통해 예약됩니다. 지금까지 Silverlight에서 직접 모드 화면 렌더링이 없다는 것을 알고 있습니다. –

1

BeginInvoke 실행 비동기 따라서 반환하고 텍스트를 변경합니다.

MSDN 설명서에서 직접 : "BeginInvoke는 비동기 적이므로 컨트롤이 호출 된 후 호출 개체로 즉시 반환됩니다."

대신 BeginInvoke에서 원하는 처리를 추가하십시오. Thread.Sleep을 한 다음 텍스트 상자를 변경하십시오.

BackgroundWorker도 이벤트에 연결할 수 있습니다. 따라서 UI가 업데이트되면 일명 BackGroundWorker 이벤트가 완료되어 다음 항목을 시작할 수 있습니다. 당신이 BgroundWorker

BackgroundWorker w = new BackgroundWorker(); 
w.DoWork += (sender, args) => 
{ 
    Thread.Sleep(5000); 
    Dispatcher.BeginInvoke(() => { 
    //your code here 
    }); 
}; 
w.RunWorkerAsync(); 
+0

Silverlight Dispatcher에는 Invoke 메서드가 없으므로 Dispatcher는 비동기 적으로 만 사용할 수 있습니다. 그럼에도 불구하고 나는 왜 첫 번째 변경이 즉시 표시되지 않는지 아직 볼 수 없습니다. – jordanpg

+0

@jordanpg 예. 죄송 합니다만, Invoke가 여전히 존재하는 경우 더 나은 대답으로 편집했습니다. –

+0

그게 내가 이미 가지고있는 것 같아요 ... 심지어 더 신비하게, 만약 내가 시도 : private void button1_Click (object sender, RoutedEventArgs e) {textBlock1.Text = "1"; Dispatcher.BeginInvoke (() => {Thread.Sleep (5000); textBlock1.Text = "2";})); textBlock1.Text = "3"; } 마지막 UI 업데이트가 발생하지 않습니다! – jordanpg

관련 문제