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

问题描述 投票:-1回答:3

我在我的项目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;
        });
    }

感谢您的关注..

c# multithreading backgroundworker
3个回答
2
投票

您可以像下面一样更改代码,它会正常工作。

  1. 将perbaharui刺激代码更改为 lbStimulus.Text = stimulus;
  2. WorkerReportsProgress改为True
  3. 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(); });
  4. 添加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(); }

希望这对你有所帮助!


0
投票

您不应该在后台线程中创建表单。这样做会将表单分配给该线程而不是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...

除此之外,你正在做的一切正确。


0
投票

您可以像使用Invoke(...)一样从后台工作者更新任何形式的标签。 (假设刺激是一个领域)。只需调用一次Invoke就足够了。 Stimulus.Invoke在刺激形式的控制线程上执行委托。所以你可以决定,你派遣线程。我建议在perbarauiStimulus中这样做,因为那会减少有人忘记拨打电话的机会。

但是您的代码存在一个潜在问题:

不要对经过的时间使用精确比较。首选使用'> ='。由于你正在处理秒,这很少是一个实际问题,但它可能会导致无限循环。

如果stimulus不是一个字段,你必须在后台worker之外创建一个Stimulus实例,因为如果你在worker方法中创建它,表单将在后台工作线程上运行它的消息循环。这消除了后台工作程序的使用,因为操作现在从sytimulus视图同步运行。

© www.soinside.com 2019 - 2024. All rights reserved.