2011-01-26 2 views
4

WPF 4 앱에서는 빠른 시스템에서 4s와 같은 컨트롤을 사용하는 매우 큰 사용자 컨트롤이 있습니다. 이 기간 동안 응용 프로그램은 전혀 반응이 없습니다.
이 컨트롤이 초기화되는 동안 주 창에 애니메이션을 표시 할 수 있습니까?사용자 정의 컨트롤을 만드는 동안 애니메이션을 표시하는 방법

다른 스레드에서 만들 수 없다는 것을 알고 있습니다. 그러나 디스패처의 우선 순위를 낮추어서 메인 윈도우에 회전 휠을 보여줄 수있는 방법이 있습니까?

(지금 내가 생각할 수있는 유일한 해결책은 더 조각으로 사용자 정의 컨트롤을 중단하고 필요한 경우에만 그들을로드하는 것입니다. 그러나이 개발의 많은을 변경하려면 시간이 걸릴 것입니다.)

갱신 1
더 명확하게하기 : 탭 페이지를 사용하는 간단한 WPF 창입니다. 새 탭 페이지가 열리면이 탭 페이지의 컨트롤이있는 사용자 정의 컨트롤을 초기화합니다. 이러한 사용자 컨트롤 중 하나는 새 탭 페이지가 표시 될 때까지 4 초가 걸리는 너무 많은 컨트롤입니다.
그래서 회전하는 바퀴가 차단 된 응용 프로그램을 사용하는 것보다 낫다고 생각했습니다.

+0

어떤 종류의 작업을 수행하는지 알기 위해 문제 코드의 적어도 한 섹션을 포함 할 수 있습니까? –

+0

@Eamon Nerbonne : 그것은 단지 통제 일뿐입니다. 9 개의 데이터 격자가있는 사용자 정의 컨트롤을 상상해보십시오. 모두 최소 12 개의 열을 가지고 있으며 무거운 스키닝을 사용합니다. 이 사용자 컨트롤을 테스트하기 위해 데이터로드를 사용하지 않도록 설정하더라도 초기화하는 데 시간이 오래 걸립니다. – Marc

+0

예, WPF가 그다지 좋지 않은 것들입니다. 평범한 자바 스크립트 + CSS + 브라우저 UI가 스타일 WPF UI보다 더 빠르고 일반적인 스타일링으로로드되는 것은 아이러니합니다. –

답변

5

나는이 사용자 컨트롤을 여러 조각으로 나누어야한다고 생각합니다. 할 수있는 일은 BackgroundWorker를 사용하여이 사용자 정의 컨트롤의 '건물'을 조정하는 것입니다. DoWork 이벤트가 발생할 때마다 Dispatcher.BeginInvoke를 사용하여 UI에 다음 컨트롤을 추가하십시오.이 기술은 다음 블로그 게시물에 설명되어 있습니다 :

http://loekvandenouweland.com/index.php/2010/12/wp7-add-user-controls-graphics-in-background-thread/

이것은 당신이로드하는 동안 애니메이션을 표시 할 수 있습니다.

+0

방금 ​​언급 한 블로그 게시물을 확인한 결과이 블로그는 실제로 매우 흥미로 웠습니다. 어쩌면 내가 그 길로 갈거야. – Marc

+1

@ ColinE의 제안과 함께 AdornerLayer를 로딩 애니메이션을 표시 할 장소로 살펴보십시오. http://msdn.microsoft.com/en-us/library/ms743737.aspx – Robaticus

+0

나는 당신의 제안을 시도했고 실제로 작동했습니다 벌금. 유일한 문제는 지금은 dev 시간이 남아 있지 않다는 것이지만, 다음부터는 처음부터이 방법으로 앱을 디자인하는 것을 기억할 것입니다. WPF를 사용하면 구성 요소 초기화에 많은 시간이 걸린다는 것은 불행한 일입니다. – Marc

2

왜 다른 스레드에서 초기화 할 수 없습니까?

  1. 핵심 WPF 초기화를 시작하기 전에 다른 스레드에서 미리로드되거나 사전 계산 된 비 WPF 이유로 초기화가 느립니다.
  2. WPF 자체가 4 초의 CPU 시간을 소비합니다 (단, 실제로는 WTF 수준의 CPU 시간입니다 ...). 그렇다면 주 스레드가로드가 완료 될 때까지 독립 UI (예 : 회전 휠)를 표시 할 수있는 자체 메시지 펌프로 다른 STA 스레드를 시작할 수 있습니다.

당신은 암시 적으로 새 Dispatcher를 만들고 백그라운드 스레드에서 실행 "대화 상자"를 만들거나 명시 적으로 자신의 Dispatcher를 만들 수 있습니다 (= 메시지 펌프).

나는 그렇게 할 다음과 같은 방법을 사용 :이 당신에게 진정한 멀티 스레드 UI를 제공

public static Dispatcher StartNewDispatcher(ThreadPriority cpuPriority = ThreadPriority.Normal) { 
    using (var sem = new SemaphoreSlim(0)) { 
     Dispatcher retval = null; 
     var winThread = new Thread(() => { 
      retval = Dispatcher.CurrentDispatcher; 
      sem.Release(); 
      Dispatcher.Run(); 
     }) { IsBackground = true, Priority = cpuPriority }; 
     winThread.SetApartmentState(ApartmentState.STA); 
     winThread.Start(); 
     sem.Wait(); 
     return retval; 
    } 
} 

; 하지만 두 가지 UI간에 데이터 바인딩이나 다른 방식으로 직접 통신 할 수 없다는 것을 의미합니다. 결국 WPF 객체는 스레드 유사성을가집니다.

이 경로를 시작하기 전에 프로파일 러를 사용하여 미리로드 할 수있는 느린 구성 요소가 없는지 확인하십시오. 옵션 1 (WPF 초기화 전에 무거운 물건을 미리로드)은 더 간단하고 깨끗합니다.

+0

두 번째 요점은 새로운 독립적 인 (이벤트 투명성) 창을 의미합니다. 맞습니까? – JYL

+1

좀 더 자세한 정보를 제공하기 위해 질문을 업데이트했습니다. 불행하게도 주 창은 사용자 정의 컨트롤과 통신해야하므로 두 개가 별도의 스레드에서 실행될 수 없습니다. – Marc

+0

음, 보통 * 두 번째 창을 의미합니다. 하지만 기술적으로는 다른 스레드에서 InteropBitmap을 통해 (예 :) 사용할 수있는 오프 스크린 버퍼가 필요합니다. 나는 전에 그것을 한 적이 없다. 하지만 가능합니다. –

0

느린 부분 (컨트롤에 속하지 않는 데이터로드)을 언급 한대로 다른 스레드로 옮기는 것이 해결책이 될 수 있습니다.

또는 VirtualizingStackPanel을 사용하여 필요한 것을 지연로드하십시오.

지연 이유를 자세히 설명해 주시겠습니까?

관련 문제