wpf c# 后台工作者在执行完成时工作

wpf c# background worker works when execution finished

我有一个 wpf 应用程序,我想在任务之前启动加载指示器并在任务完成后结束。但是指标在任务执行后启动。 我正在尝试的是如下。

      private void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
    {
        worker.RunWorkerAsync(); // this supposed to start progress bar
        _RunAllScripts_Click();

    }

   private void worker_DoWork(object sender, DoWorkEventArgs e)
    {

        this.Dispatcher.Invoke(() =>
        {
            ... Start loading indicator
        });
    }

    private void worker_RunWorkerCompleted(object sender,
                                           RunWorkerCompletedEventArgs e)
    {
        ... End loading indicator
    }

但加载指示器仅在 _RunAllScripts_Click();方法执行完毕。 (我发现在取消订阅 worker_RunWorkerCompleted 事件后,进度条开始并保持原样,因为没有代码可以结束它)。

我还想补充一点,断点在执行前命中 worker_DoWork 方法,但 UI 在执行后更新,如我上面所述。

感谢您提供的所有帮助。

如果我是你,我会为此使用 async + await 关键字

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        // this is where you would enable your indicator
        Button.IsEnabled = false;

        await Task.Run(
            () =>
            {
                // this is where you put your work, which should be executed in the background thread.
                Thread.Sleep(2000);
            });

        // this is where you would disable it
        Button.IsEnabled = true;
    }

使用 async/await 即可。 await 关键字将允许您 运行 在没有 affecting/blocking UI 线程的情况下工作(允许消息泵送仍然发生)。工作完成后,将执行 await 关键字后的任何代码。

请注意,我还将 await 工作包含在 InvokeAsync 调用中,因为您正在进行的额外工作似乎需要 UI 线程访问权限。

private async void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
    //TODO  ... Start loading indicator

    await Task.Run(async ()=> 
    {
        await Application.Current.Dispatcher.InvokeAsync(()=>
        {
            _RunAllScripts_Click();
        });
    });

    //TODO  ... End loading indicator
}

亲爱的好心人帮助我解决这个问题,谢谢大家。 这对我有用,希望对所有人有用。

BackgroundWorker bwTestAll = new BackgroundWorker() { WorkerReportsProgress = true };

 bwTestAll.DoWork += new DoWorkEventHandler(TestAll);
        bwTestAll.RunWorkerCompleted += TestAll_RunWorkerCompleted;

//this is where I initialize my loading ring and other stuff and marshall background
//worker to do the main work
 Dispatcher.Invoke(new Action(() =>
                {
                    EnableLoading = true;
                    RunAllScriptsTest.IsEnabled = false;

                }), DispatcherPriority.ContextIdle);

                bwTestAll.RunWorkerAsync();


//this is my main work
  void TestAll(object sender, DoWorkEventArgs e)
    {
        presenter.RunAllScripts(true);
    }

//this is where I do my post-work stuff
 private void TestAll_RunWorkerCompleted(object sender,
                                   RunWorkerCompletedEventArgs e)
    {
        Dispatcher.Invoke(new Action(() =>
        {
            /
            EnableLoading = false;
            RunAllScriptsTest.IsEnabled = true;
            DbExecGrid = this.ExecutionResults;
            ShowOrHideExecGrid(this.EnableOrDisableGrid);

        }), DispatcherPriority.ContextIdle);
    } 

*请注意,"DispatcherPriority.ContextIdle" 的 Dispatcher 适合我。