簡體   English   中英

為什么 WPF 進度條動畫不在函數調用時啟動?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM