2011-03-30 102 views
2

我使用浏览文件对话框来允许用户选择多个图像。如果选择了很多图像,按预期方式需要一点。以下是我对所选图像做的一个例子。我将文件路径循环到图像并创建用户控件的实例,用户控件具有图像控件和其他一些控件。我创建此控件的实例,然后将其添加到在关联窗口xaml文件中创建的现有的stackPanel。下面的示例工作正常,但我试图更好地理解BackGroundWorker,我了解如何设置它的基本知识,它的事件,并传回一个值可以更新进度栏,但因为我的循环在下面的启动时间将usercontrol实例添加到现有的stackPanel中,它将不起作用,处于不同的线程中。 BackGroundWorker是否适用于这样的示例?如果是这样,更新线程之外的ui(我的堆栈面板)的最佳方法是什么?我对wpf相当陌生,除了测试它之外,从未使用过BackGroundWorker,它只是用int值更新进度,所以我希望这个问题有意义,如果我的目标只是让我知道。感谢您的任何想法。wpf BackgroundWorker - 关于更新UI

我现在正在做这件事的例子,它工作正常。

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(); 
    } 
}  

这个类我有这个,所以我可以有进度刷新以下:

​​

回答

2

退房这篇文章 Building more responsive apps with the Dispatcher

现在,你有怎样的感觉调度员的工作,你可能会惊讶地发现在大多数情况下你不会找到它的用处。在Windows Forms 2.0中,Microsoft引入了非UI线程处理类来简化用户界面开发人员的开发模型。这个类叫做BackgroundWorker

在WPF中,这个模型是用一个DispatcherSynchronizationContext类扩展的。通过使用BackgroundWorker,Dispatcher被自动调用以调用跨线程方法调用。好消息是,因为你很可能已经熟悉了这个共同的模式,你可以继续在新的WPF使用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

单独使用一个BackgroundWorker不会解决您的问题,因为在DoWork部分创建的元素仍然源自非UI线程。您必须致电Freeze您打算在另一个线程上使用的任何对象。但是只有某些UI对象可以冻结。您可能需要在后台线程上加载图像BitmapImage,然后在UI线程上创建用户控件的其余部分。这可能仍然可以实现您的目标,因为在图像中加载可能是最重量级的操作。

只记得将BitmapImage.CacheOption设置为OnLoad,所以它在创建对象时实际加载图像,而不是等到它需要显示。