Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#在线程期间从外部方法更新进度表_C#_Multithreading - Fatal编程技术网

c#在线程期间从外部方法更新进度表

c#在线程期间从外部方法更新进度表,c#,multithreading,C#,Multithreading,准备好了否决票,但我真的离与这个后台工作人员处理线程的细节还有一段距离,但我已经设法为我想要的东西找到了一个结构: public class cls1 { private FormProgress myProgForm = new FormProgress(); public BackgroundWorker worker = new BackgroundWorker(); // new instance of bkgworker

准备好了否决票,但我真的离与这个后台工作人员处理线程的细节还有一段距离,但我已经设法为我想要的东西找到了一个结构:

public class cls1
    {

        private FormProgress myProgForm = new FormProgress();
        public BackgroundWorker worker = new BackgroundWorker();   // new instance of bkgworker

        public void prepare_a_job()
        {
            worker.WorkerReportsProgress = true;                // Allows the worker to report progress
            worker.ProgressChanged += worker_ProgressChanged;   // Adding handler to update progress
            worker.DoWork += job1;                              // Adding handler for the ACTUAL JOB METHOD

            myProgForm.Show();                                  // Show the prog update form
            worker.RunWorkerAsync();                            // Start the job, already! Wo lo loo
        }

        void job1(object sender, EventArgs e)                   // Do 0 to 100
        {
            for (int i = 0; i <= 100; i++)
            {
                (sender as BackgroundWorker).ReportProgress(i); // ReportProgress uses percentages
                Thread.Sleep(50);
            }
            // THIS IS WHERE I'D INSERT ANOTHER METHOD
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if(e.ProgressPercentage == 100)  // If the % gets to 100
            {
                myProgForm.UPDATEME("", true);   // then pass true to close progressForm
            }
            else
            {
                myProgForm.UPDATEME("Counting\n" + e.ProgressPercentage);  // else just update 
            }

        }
    }
乱七八糟的,对吧?但它是有效的(我24小时来一直在努力寻找/学习这些东西,这是我第一次远程理解

我遇到的问题是,在
job1
例程中,从我想调用的任何其他方法调用UPDATEME()方法-例如,实际上,这不仅仅是浪费时间的循环,而是以各种顺序调用大量其他方法的一组条件

我尝试将第二个方法插入到
job1
中,并在第二个方法调用
UPDATEME
中,但这不是线程安全的跨线程更新

我认为这可能与调用有关,但后来我也读到了一些关于MSDN BackgroundWorker的内容,它是另一种在没有调用的情况下允许线程安全的方法,然后我的头爆炸了,我的大脑掉了出来

如何在代码中的任何其他方法中始终引用我的
ProgressForm.UPDATEME(“新进度消息”)
方法?

编辑:

例如,我会在
job1
调用中插入对第二个方法的调用

void myOtherMethod()
    {
        (worker).ReportProgress(0);
        myProgForm.UPDATEME("Doing part 1");
        Thread.Sleep(1000);
        myProgForm.UPDATEME("Doing part 2");
        Thread.Sleep(1000);
        myProgForm.UPDATEME("Doing part 3");
        Thread.Sleep(1000);
    }
如何始终引用我的ProgressForm.UPDATEME(“新进度”) 我的代码中任何其他方法中的message“)方法

像这样:

public void UPDATEME(string MSG, bool finish = false)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new MethodInvoker(() => this.UPDATEME(MSG, finish)));
    }
    else
    {
        this.label1.Text = MSG;
        if (finish) { this.Close(); }
    }
}
我真的不明白如何从内部调用该方法 获取在第一级之外调用该方法的事实 线程

一开始令人困惑,因为这是一个递归调用。“肉”是
Invoke()
在创建控件的同一线程(本例中为表单本身)上运行其中的任何内容。当我们第二次输入该方法时(由于递归),检查返回false,我们在UI线程上安全地运行else块

无论是否需要,您都可以通过始终调用
Invoke()
来摆脱检查(和递归):

public void UPDATEME(string MSG, bool finish = false)
{
    this.Invoke(new Action(() =>
    {
        this.label1.Text = MSG;
        if (finish) { this.Close(); }
    }));
}
下面是另一个版本,它仍然检查是否需要
Invoke()
,但不使用递归(不太容易混淆,但我们现在引入了重复代码):

对于那些“面向细节”的方法/变体(我使用的是
MethodInvoker
而不是
Action
),显示了一种删除上述重复代码的方法:

public void UPDATEME(string MSG, bool finish = false)
{
    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)delegate
        {
            this.updater(MSG, finish);
        });
    }
    else
    {
        this.updater(MSG, finish);
    }
}

private void updater(string MSG, bool finish = false) // NOT thread safe, thus the private (don't call directly)
{
    this.label1.Text = MSG;
    if (finish) { this.Close(); }
}

你熟悉
event
s吗?我想这就是你想要的。为什么你不能直接调用
ReportProgress()
来自
job1
方法中的其他方法?这与在此循环中调用它没有什么区别。
ProgressChanged
事件处理程序仍会将更新发送到您的UI。也许您可以向我们展示您迄今为止扩展此当前示例的尝试。是和否,我对事件处理程序相当满意在旧的Excel VBA中,甚至在c#/vb.Net中为事件添加了一些处理程序,但当涉及到异步调用事件时,我是一个完全的处女,我正在边做边学!只是做得不太好:DI尝试调用行
(发送方作为BackgroundWorker)。ReportProgress(I)
在另一个方法中,只使用
工作者
作为
发送者
位(将其移动到公共属性而不是方法内)但是它仍然说它不是跨线程安全的,我编辑它是为了显示调用更新事件的第二个方法,但我认为现在唯一可以继续的方法是始终在第一级方法(
Job1
)上调用该更新。因此,任何嵌套方法都必须完全执行,返回报告,然后第1级将调用更新。这并不理想,而且我仍然不明白,如果线性/同步调用,为什么嵌套线程不能调用该方法,但哦,好吧!哇,我在MSDN页面上读到了这一点,我以为它适用于除BackgroundWorker之外的其他线程类型,我甚至开始键入类似的内容(但在Lamda表达式中可能会迷失方向)-我真的不明白如何从内部调用该方法来绕过该方法在1级线程之外调用的事实,但非常感谢为我添加了一行。尝试了它,它工作了!!!
public void UPDATEME(string MSG, bool finish = false)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() =>
        {
            this.label1.Text = MSG;
            if (finish) { this.Close(); }
        }));
    }
    else
    {
        this.label1.Text = MSG;
        if (finish) { this.Close(); }
    }
}
public void UPDATEME(string MSG, bool finish = false)
{
    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)delegate
        {
            this.updater(MSG, finish);
        });
    }
    else
    {
        this.updater(MSG, finish);
    }
}

private void updater(string MSG, bool finish = false) // NOT thread safe, thus the private (don't call directly)
{
    this.label1.Text = MSG;
    if (finish) { this.Close(); }
}