2013-10-17 32 views
0

因此,这是我第一次使用委托,事件,Backgroundworkers,WPF ...几乎一切都是新的。我有一个运行,我想在报告进度长时间运行的方法外部类:从外部方法更新UI进度条

public class ShortFileCreator 
{ 
    public void CreateShortUrlFile(string outputfilepath) 
    {   
     foreach(string line in lines) 
     { 
       //work work work processing file 
       if (ReportProgress != null) 
       { 
       //report progress that a file has been processed 
        ReportProgress(this, new ProgressArgs {TotalProcessed = numberofurlsprocessed 
                 , TotalRecords = _bitlyFile.NumberOfRecords}); 
       } 
     } 
    } 

    public delegate void ReportProgressEventHandler (object sender, ProgressArgs args); 

    public event ReportProgressEventHandler ReportProgress; 

    public class ProgressArgs : EventArgs 
    { 
     public int TotalProcessed { get; set; } 
     public int TotalRecords { get; set; } 
    } 
} 

在我的WPF的形​​式,我想开球CreateShortUrlFile方法和更新形式的进度条。

private void btnRun_Click(object sender, RoutedEventArgs e) 
    { 
     var shortFileCreator = new ShortFileCreator();   

     _worker = new BackgroundWorker 
     { 
      WorkerReportsProgress = true, 
      WorkerSupportsCancellation = true 
     }; 

     shortFileCreator.ReportProgress += ShortFileCreator_ReportProgress; 

     _worker.DoWork += delegate(object s, DoWorkEventArgs args) 
     { 
      _bitlyFileWorker.CreateShortUrlFile(saveFileDialog.FileName); 
     }; 

     _worker.RunWorkerAsync(); 
    } 

    protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e) 
    { 
     //update progress bar label 
     txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords); 
     //update progress bar value 
     progress.Value = (double) e.TotalProcessed/e.TotalRecords; 
    } 

然而,当我运行它,它处理一个行,然后我得到异常:因为另一个线程拥有它调用线程不能访问该对象。其他线程拥有这个? ReportProgress事件不应该将ProgressArgs返回给任何订户?

回答

1

这是因为UI控件像ProgressBarTextBox不能被另一个线程被感动,在这种情况下,你正试图从BackgroundWorker线程更新。

解决的办法是Invoke回调到UI线程,你可以使用Dispatcher

protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e) 
{ 
    Dispatcher.Invoke((Action)delegate 
    { 
     //update progress bar label 
     txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords); 
     //update progress bar value 
     progress.Value = (double) e.TotalProcessed/e.TotalRecords; 
    }); 
} 
+0

工作完全做到这一点。谢谢。 – MickJuice