[英]Why doesn't the WPF Progressbar Animation Start On Function Call?
我正在處理我的第一個 WPF 項目,我正在嘗試為一個冗長的函數添加一個進度條。 我添加了消息框來通知我函數成功/錯誤。 我需要使用 IsIndeterminate 類型的進度條。 RunWorkerAsync() 行也被正確調用,但是當 DoWork 函數調用其中的冗長函數時,動畫不起作用。當函數結束並且消息框彈出時,動畫工作正常。
private void ButtonPipeline_Click(object sender, RoutedEventArgs e)
{
pbStatus.IsIndeterminate = true;
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.DoWork += worker_DoWorkPipeline_Click;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("Sync Interrupted.", "Message", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
pbStatus.IsIndeterminate = false;
MessageBox.Show("Synced Completed.", "Sync Complete", MessageBoxButton.OK, MessageBoxImage.None);
pbStatus.Value = 0;
}
}
void worker_DoWorkPipeline_Click(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
var worker = sender as BackgroundWorker;
try
{
var pipeline = GetPipeline(); //THis function throws "The calling thread cannot access this object because a different thread owns it"
if (pipeline.Name.Equals("<None>"))
{
MessageBox.Show("Please select a pipeline.", "Missing Data", MessageBoxButton.OK, MessageBoxImage.Warning);
worker.CancelAsync();
}
else
{
aLongFunction(pipeline);
MessageBox.Show("Pipeline: " + pipeline + Environment.NewLine + "Successfully Synced.", "Sync Complete", MessageBoxButton.OK, MessageBoxImage.None);
}
if (worker.CancellationPending == true)
{
pbStatus.IsIndeterminate = false;
pbStatus.Value = 0;
e.Cancel = true;
return;
}
}
catch (Exception ex)
{
worker.CancelAsync();
MessageBox.Show(ex.InnerException.ToString(), "Exception Occoured!", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
}
private void aLongFunction(Pipeline pipeline)
{
var session = new SynchronizationSession(pipeline);
session.Run();
MessageBox.Show("Successfully Synced.", "Sync Complete", MessageBoxButton.OK, MessageBoxImage.None);
}
public void Run()
{
anotherFunction();
}
private Pipeline GetPipeline()
{
var pipeline = (Pipeline)DropdownSyncPipeline.SelectedItem; //This throws and error since trying to access another UI Object.
if (null != pipeline)
{
if (0 == pipeline.Id)
{
var p = PerfOtherPipeline.Text;
if (!string.IsNullOrEmpty(p)) pipeline = BrokerDataCache.Pipelines.Find(p_ => p.Equals(p_.Name));
}
}
return pipeline;
}
BackgroundWorker 是一種幫助抽象線程處理的工具,但是您發布的代碼以一種奇怪的方式使用它:
在 DoWork ( worker_DoWorkPipeline_Click ) 處附加到它的事件將在與 UI 不同的線程中運行,但是由於您將整個方法包裝在對 Dispatcher 的調用中,因此所有aLongFunction都將在與 UI 相同的線程中運行。
從您對錯誤的描述來看,問題是進度條停止了動畫,對嗎? 這樣做的原因是,只要使用 Dispatcher.Invoke 在其線程上運行代碼,UI 就不會響應。
此問題的解決方案是從worker_DoWorkPipeline_Click中刪除 Invoke 方法。
但是,如果 SynchronizationSession 中的代碼訪問項目中的任何 UI 對象,則可能會出現異常,因為 WPF UI 對象通常只能在同一線程上訪問。 您尚未提供該功能的代碼,因此我們無法從您提供的內容中得知。
如果 SynchronizationSession 或在 Backgroundworker 中運行的其他任何東西需要更新 UI,請僅對需要更新 UI 的代碼部分使用 Dispatcher.Invoke。 這將避免在整個操作過程中阻塞 UI,但僅在必要時才這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.