猿问

如何使用 backgroundworker 进程 c# 以另一种形式更改标签?

我的项目c#中有2个表单(formA和formB),当我单击formA中的按钮时,我想在backgroundworker中运行一些进程。


我可以从后台工作人员更新为 formB 中的标签吗?这是formA中的代码


        private void button1_Click_1(object sender, EventArgs e)

    {

        backgroundWorker1.RunWorkerAsync();

    }


    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

    {

        Stimulus stimulus = new Stimulus();

        Stopwatch watch = new Stopwatch();

        stimulus.Show();

        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus("+"); });

        watch.Start();

        do

        {


        } while (watch.Elapsed.Seconds != 2);

        watch.Restart();

        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus("MAJU"); });

        do

        {


        } while (watch.Elapsed.Seconds != 6);

        watch.Restart();

        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus(""); });

        do

        {


        } while (watch.Elapsed.Seconds != 2);

        watch.Stop();

        stimulus.Close();

    }

和表单B中的代码


        public Stimulus()

    {

        InitializeComponent();

        FormBorderStyle = FormBorderStyle.None;

        WindowState = FormWindowState.Maximized;

    }

    public void perbaharuiStimulus(string stimulus)

    {

        this.Invoke((MethodInvoker)delegate

        {

            lbStimulus.Text = stimulus;

        });

    }

感谢您的关注..


德玛西亚99
浏览 211回答 3
3回答

烙印99

您可以像下面这样更改您的代码,它会正常工作。将 perbaharuiStimulus 代码更改为lbStimulus.Text = stimulus;更改WorkerReportsProgress为True更改backgroundWorker1_DoWork以下    Stimulus stimulus = new Stimulus();    Stopwatch watch = new Stopwatch();    backgroundWorker1.ReportProgress(1, stimulus);    watch.Start();    do    {    } while (watch.Elapsed.Seconds != 2);    watch.Restart();    backgroundWorker1.ReportProgress(2, stimulus);    do    {    } while (watch.Elapsed.Seconds != 6);    watch.Restart();    backgroundWorker1.ReportProgress(3, stimulus);    do    {    } while (watch.Elapsed.Seconds != 2);    watch.Stop();    stimulus.Invoke((MethodInvoker)delegate { stimulus.Close(); });添加backgroundWorker1_ProgressChanged事件并将以下代码放入其中private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){    Stimulus stimulus = ( Stimulus)e.UserState;    if(e.ProgressPercentage==1)        stimulus.perbaharuiStimulus("+");    if (e.ProgressPercentage == 2)        stimulus.perbaharuiStimulus("MAJU");    if (e.ProgressPercentage == 3)        stimulus.perbaharuiStimulus("");    stimulus.Show();}我希望这对你有帮助!

慕少森

您可以Invoke(...)像您所做的那样使用后台工作人员以任何形式更新标签。(假设刺激是一个场)。调用一次 Invoke 就足够了。Stimulus.Invoke在激励表单的控制线程上执行委托。所以你可以决定,当你调度线程时。我建议在 中执行此操作perbarauiStimulus,因为这样可以减少有人忘记发送呼叫的机会。但是您的代码存在一个潜在问题:不要使用经过时间的精确比较。更喜欢使用'>='。由于您正在处理秒数,因此这很少会成为实际问题,但可能会导致无限循环。如果stimulus不是字段,则必须在后台工作人员Stimulus 之外创建一个实例,因为如果您在工作人员方法内创建它,表单将在后台工作人员线程上运行其消息循环。这消除了后台工作人员的使用,因为该操作现在从 sytimulus 视图同步运行。

萧十郎

您不应该在后台线程中创建表单。这样做会将表单分配给该线程而不是 UI 线程,这意味着该表单现在位于与消息泵不同的线程上。解决此问题的方法是在 UI 线程上调用表单的实例化和查看,然后您的以下Invoke调用应该可以工作。Stimulus stimulus;this.Invoke((MethodInvoker)delegate{    stimulus = new Stimulus();    stimulus.Show();});//No need to invoke this since perbaharuiStimulus() calls Invoke() as well.stimulus.perbaharuiStimulus("+");//The rest of your code...除此之外,您所做的一切都是正确的。
随时随地看视频慕课网APP
我要回答