2011-03-30 4 views
2

파일 탐색 대화 상자를 사용하여 사용자가 여러 이미지를 선택할 수 있습니다. 많은 이미지가 선택되면 예상대로 조금 걸립니다. 다음은 내가 선택한 이미지로 수행하는 작업의 예입니다. 나는 파일 경로를 통해 이미지를 반복하고 사용자 정의 컨트롤의 인스턴스를 만들고, 사용자 정의 컨트롤에는 Image 컨트롤과 몇 가지 다른 컨트롤이 있습니다. 이 컨트롤의 인스턴스를 만든 다음이를 관련 창 xaml 파일에 생성 된 기존 stackPanel에 추가합니다. 바로 아래의 예제는 잘 작동하지만, BackGroundWorker를 더 잘 이해하려고 노력하고 있습니다. 이벤트를 설정하고 진행률 막대를 업데이트 할 수있는 값을 전달하는 방법에 대한 기본 사항을 얻습니다.하지만 루프가 필요하기 때문에 아래의 가동 시간은 기존 stackPanel에 usercontrol 인스턴스를 추가합니다. 작동하지 않으며 다른 스레드에 있습니다. BackGroundWorker는 이와 같은 예를 위해 작동할만한 것이 있습니까? 그렇다면 스레드 외부에있는 ui (내 스택 패널)를 업데이트하는 가장 좋은 방법은 무엇입니까? 나는 상당히 새로운 wpf이고 BackGroundWorker를 사용한 적이 없는데, 단지 int 값으로 진행 상황을 업데이트하는 것 뿐이므로이 질문이 의미가 있기를 바란다. 어떤 생각을 해줘서 고마워.wpf BackgroundWorker - UI 업데이트 관련

내가 지금하고있는 일의 예. 제대로 작동합니다. 당신은 어떻게 감각이 이제

public static class extensionRefresh { 
    private static Action EmptyDelegate = delegate() { }; 

    public static void Refresh(this UIElement uiElement) { 
     uiElement.Dispatcher.Invoke(DispatcherPriority.Background, EmptyDelegate); 
    } 
} 

답변

2

체크 아웃 Building more responsive apps with the Dispatcher

에이 기사를 :이 그래서 ProgressBar의 새로 고침을 가질 수있는이 클래스 아래

protected void myMethod(string[] fileNames) { 
    MyUserControl uc; 

    foreach (String imagePath in fileNames) { 
     uc = new MyUserControl(); 
     uc.setImage(imagePath); 
     stackPanel.Children.Add(uc); 
     progressBar.Value = ++counter; 
     progressBar.Refresh(); 
    } 
}  

Dispatcher가 작동하면 대부분의 경우에 사용하지 않을 것이라는 점을 알고 놀랄 수 있습니다. Windows Forms 2.0에서 Microsoft는 사용자 인터페이스 개발자를위한 개발 모델을 단순화하기 위해 비 UI 스레드 처리 클래스를 도입했습니다. 이 클래스는 BackgroundWorker라고합니다.

WPF에서이 모델은 DispatcherSynchronizationContext 클래스로 확장됩니다. BackgroundWorker를 사용하여 Dispatcher는 자동으로 교차 스레드 메소드 호출을 호출합니다. 좋은 소식은 당신이 아마이 일반적인 패턴을 이미 잘 알고 있기 때문에, 당신의 새로운 WPF에있는 BackgroundWorker를 계속 사용할 수 있다는 것입니다 혼자있는 BackgroundWorker를하지 않습니다 사용

는 기본적으로 접근이

BackgroundWorker _backgroundWorker = new BackgroundWorker(); 

// Set up the Background Worker Events 
_backgroundWorker.DoWork += _backgroundWorker_DoWork; 
_backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted; 

// Run the Background Worker 
_backgroundWorker.RunWorkerAsync(5000); 

// Worker Method 
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Do something 
} 

// Completed Method 
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // Doing UI stuff 
    if (e.Cancelled) 
    { 
     statusText.Text = "Cancelled"; 
    } 
    else if (e.Error != null) 
    { 
     statusText.Text = "Exception Thrown"; 
    } 
    else 
    { 
     statusText.Text = "Completed"; 
    } 
} 
1

입니다 프로젝트 DoWork 부분에서 생성 된 요소는 여전히 UI가 아닌 스레드에서 생성 되었기 때문에 문제를 해결할 수 있습니다. 다른 스레드에서 사용할 객체에 Freeze을 호출해야합니다. 그러나 특정 UI 객체 만 고정 할 수 있습니다. 백그라운드 스레드에서 이미지를 BitmapImage으로로드 한 다음 UI 스레드에서 나머지 사용자 컨트롤을 만들어야 할 수 있습니다. 이미지로드는 아마도 가장 중량이 큰 작업 일 수 있기 때문에 이것은 여전히 ​​목표를 달성 할 수 있습니다.

BitmapImage.CacheOptionOnLoad으로 설정하는 것이 좋습니다. 실제로 이미지를 표시해야 할 때까지 기다리지 않고 이미지를로드합니다.