为什么 WPF 进度条动画不在函数调用时启动?

Why doesn't the WPF Progressbar Animation Start On Function Call?

我正在处理我的第一个 WPF 项目,我正在尝试为一个冗长的函数添加一个进度条。 我添加了消息框以在功能 success/error 上通知我。我需要使用 IsIndeterminate 类型的进度条。 RunWorkerAsync() 行也被正确调用,但是当 DoWork 函数调用其中的冗长函数时,动画不会 work.When 函数结束并且消息框弹出动画工作正常。

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 中的任何其他 运行ning 需要更新 UI,请仅对需要更新的代码部分使用 Dispatcher.Invoke 需要更新 UI。这将避免在整个操作过程中阻塞 UI,但仅在必要时才这样做。