我创建了一个wpf应用程序。 在我的应用程序中,我打开一个窗口,我在后台复制一些文件。 我希望在复制过程中显示和更新进度条。
我尝试使用BackgroundWorker:
public partial class FenetreProgressBar : Window
{
private readonly BackgroundWorker worker = new BackgroundWorker();
public FenetreProgressBar(ObservableCollection<Evenement.FichierJoint> CollectionFicJointsToAdd)
{
InitializeComponent();
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.ProgressChanged +=worker_ProgressChanged;
worker.RunWorkerAsync(CollectionFicJointsToAdd);
}
private void ProgressChanged(double Persentage, ref bool Cancel)
{
if (Cancel)
this.Close();
worker.ReportProgress((int)Persentage);
}
private void Completedelegate()
{
this.Close();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
ObservableCollection<Evenement.FichierJoint> collection = e.Argument as ObservableCollection<Evenement.FichierJoint>;
//2) On ajoute les fichiers joints à l'évènements ( ce qui va donc les copier dans le répertoire paramétré)
foreach (Evenement.FichierJoint FichierJoint in collection)
{
if (FichierJoint.strPathFichier.Length > 0)
{
Evenement.FichierJoint monFichierJoint = new Evenement.FichierJoint(FichierJoint.strPathFichier, App.obj_myEvenement.strEvtNumeroString);
MaProgressBar.Minimum = 0;
MaProgressBar.Maximum = 100;
monFichierJoint.copyObject.OnProgressChanged += ProgressChanged;
monFichierJoint.copyObject.OnComplete += Completedelegate;
monFichierJoint.AddFichierJoint();
}
}
}
private void worker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
// Traitement terminé, on ferme la fenetre
this.Close();
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MaProgressBar.Value = e.ProgressPercentage;
}
}
当程序到这里时:
MaProgressBar.Minimum = 0;
MaProgressBar.Maximum = 100;
我有一个例外:“调用线程无法访问此对象,因为另一个线程拥有它”。
我已经阅读了google和stackoverflow上的几个答案,但我不尝试将此方法与BackgroundWorker一起使用。
任何人都可以帮助我避免这种异常并解决问题吗?
非常感谢,
最好的问候:)
答案 0 :(得分:1)
你cannot modify UI objects from background worker
。您需要在invoke
上dispatcher
这样的方法 -
App.Current.Dispatcher.Invoke((Action)delegate
{
MaProgressBar.Minimum = 0;
MaProgressBar.Maximum = 100;
});
但由于您只需要set maximum an minimum values
,我建议您在constructor
-
public FenetreProgressBar(ObservableCollection<Evenement.FichierJoint>
CollectionFicJointsToAdd)
{
InitializeComponent();
MaProgressBar.Minimum = 0;
MaProgressBar.Maximum = 100;
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.ProgressChanged +=worker_ProgressChanged;
worker.RunWorkerAsync(CollectionFicJointsToAdd);
}
答案 1 :(得分:0)
为什么不使用C#new async并等待新功能/关键字?它们专门设计用于在进行冗长操作时使UI响应。
答案 2 :(得分:0)
你应该试试这个:
_backgroundWorker.OnProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
然后
// Event handler
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Update main thread here
}