WPF C# - 从另一个线程更新进度条

ack*_*k__ 15 c# wpf multithreading progress-bar

我试图从其他类中运行的其他线程更新进度条.为了解释我的所作所为,我认为一张图片会更好.我想更新// HERE点的进度条:在此输入图像描述

我试过使用一个委托,尝试使用ReportProgress,我想我基本上已经尝试使用谷歌在前100个结果中报告的所有内容,但没有成功.我还在学习WPF,这可能是愚蠢的方式继续,我正在寻找一种快速而肮脏的方式来完成工作,但随时告诉我应该为更清洁的应用程序重新设计.

编辑:更多代码.

在ExecutorWindow.xaml.cs中:

public void RunExecutor()
{
    // CREATE BACKGROUNDWORKER FOR EXECUTOR
    execBackground.DoWork += new DoWorkEventHandler(execBackground_DoWork);
    execBackground.RunWorkerCompleted += new RunWorkerCompletedEventHandler(execBackground_RunWorkerCompleted);
    execBackground.ProgressChanged += new ProgressChangedEventHandler(execBackground_ProgressChanged);
    execBackground.WorkerReportsProgress = true;
    execBackground.WorkerSupportsCancellation = true;
    // RUN BACKGROUNDWORKER
    execBackground.RunWorkerAsync();
}
private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run();            
}

private void execBackground_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("RunWorkerCompleted execBackground");
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}

// TESTING 
private void updateProgressBar(int i)
{
    ExecutorProgressBar.Value += i;
}

public delegate void callback_updateProgressBar(int i);
Run Code Online (Sandbox Code Playgroud)

在Executor.cs中:

public void Run()
{
    string[] options = new string[2];
    int i = 0;

    while (LeftToRun > 0)
    {
        if (CurrentRunningThreads < MaxThreadsRunning)
        {
            BackgroundWorker myThread = new BackgroundWorker();
            myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
            myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
            myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
            myThread.WorkerReportsProgress = true;
            myThread.WorkerSupportsCancellation = true;

            myThread.RunWorkerAsync(new string[2] {opt1, opt2});

            // HERE ?
            CurrentRunningThreads++;
            i++;
            LeftToRun--;

        }
    }

    while (CurrentRunningThreads > 0) { }
    logfile.Close();
    MessageBox.Show("All Tasks finished");
}

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
    string[] options = (string[])e.Argument;
    string machine = options[0];
    string script = options[1];
    // UPDATE HERE PROGRESSBAR ?
    RemoteProcess myRemoteProcess = new RemoteProcess(machine, script);
    string output = myRemoteProcess.TrueExec();
    // UPDATE HERE PROGRESSBAR ?
    this.logfile.WriteLine(output);
}

private void backgroundWorkerRemoteProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    CurrentRunningThreads--;
}

private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //myExecWindow.ExecutorProgressBar.Value = e.ProgressPercentage; // TESTING
    //ExecutorWindow.callback_updateProgressBar(1); // TESTING 
}
Run Code Online (Sandbox Code Playgroud)

编辑2:我明白了!事实很简单,但我想我一直在寻找太近了.

在我的ExecutorWindow类中:

private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run(sender);
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}
Run Code Online (Sandbox Code Playgroud)

在我的Executor课程中:

private BackgroundWorker myExecutorWindow;

[...]

public void Run(object sender)
{
            myExecutorWindow = sender as BackgroundWorker;
            string[] options = new string[2];
            int i = 0;

            while (LeftToRun > 0)
            {
                if (CurrentRunningThreads < MaxThreadsRunning)
                {
                    BackgroundWorker myThread = new BackgroundWorker();
                    myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
                    myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
                    myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
                    myThread.WorkerReportsProgress = true;
                    myThread.WorkerSupportsCancellation = true;

                    myThread.RunWorkerAsync(new string[2] {opt1, opt2});

                    CurrentRunningThreads++;
                    i++;
                    LeftToRun--;      
                }
            }

[...]

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
            myBackgroundWorker.ReportProgress(1);
            // PROCESSING MY STUFF HERE
            myBackgroundWorker.ReportProgress(1);
        }

        private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            myExecutorWindow.ReportProgress(1);
        }
Run Code Online (Sandbox Code Playgroud)

谢谢 !

Teo*_*gul 11

您可以使用此基本示例在UI线程上运行任何方法

this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() 
{       
   this.progressBar.Value= 20; // Do all the ui thread updates here
}));
Run Code Online (Sandbox Code Playgroud)

在Dispatcher.Invoke(...)中运行命令,您实际上可以从任何工作线程与UI进行交互,否则您将获得异常.

如果你真的需要对后台线程和主要(UI)线程更新进行最终控制,那么这是一个很棒的教程:http://blog.decarufel.net/2009/03/good-practice-to-use -dispatcher功能于wpf.html


ack*_*k__ 1

我得到了它!事实上很简单,但我想我一直看得太近而找不到答案。

在我的 ExecutorWindow 类中:

private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
    myExecutor = new Executor(arg1, arg2);
    myExecutor.Run(sender);
}

private void execBackground_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ExecutorProgressBar.Value += 1;
}
Run Code Online (Sandbox Code Playgroud)

在我的执行者课程中:

private BackgroundWorker myExecutorWindow;

[...]

public void Run(object sender)
{
            myExecutorWindow = sender as BackgroundWorker;
            string[] options = new string[2];
            int i = 0;

            while (LeftToRun > 0)
            {
                if (CurrentRunningThreads < MaxThreadsRunning)
                {
                    BackgroundWorker myThread = new BackgroundWorker();
                    myThread.DoWork += new DoWorkEventHandler(backgroundWorkerRemoteProcess_DoWork);
                    myThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorkerRemoteProcess_RunWorkerCompleted);
                    myThread.ProgressChanged += new ProgressChangedEventHandler(backgroundWorkerRemoteProcess_ProgressChanged);
                    myThread.WorkerReportsProgress = true;
                    myThread.WorkerSupportsCancellation = true;

                    myThread.RunWorkerAsync(new string[2] {opt1, opt2});

                    CurrentRunningThreads++;
                    i++;
                    LeftToRun--;      
                }
            }

[...]

private void backgroundWorkerRemoteProcess_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker myBackgroundWorker = sender as BackgroundWorker;
            myBackgroundWorker.ReportProgress(1);
            // PROCESSING MY STUFF HERE
            myBackgroundWorker.ReportProgress(1);
        }

        private void backgroundWorkerRemoteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            myExecutorWindow.ReportProgress(1);
        }
Run Code Online (Sandbox Code Playgroud)