简体   繁体   English

C#从后台工作者不断更新GUI

[英]C# update GUI continuously from backgroundworker

I have created a GUI (winforms) and added a backgroundworker to run in a separate thread. 我创建了一个GUI(winforms)并添加了一个后台工作程序以在一个单独的线程中运行。 The backgroundworker needs to update 2 labels continuously. 后台工作人员需要不断更新2个标签。 The backgroundworker thread should start with button1 click and run forever. backgroundworker线程应该以button1单击开始并永远运行。

    class EcuData 
    {
        public int RPM { get; set; }
        public int MAP { get; set; }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        EcuData data = new EcuData
        {
            RPM = 0,
            MAP = 0
        };
        BackWorker1.RunWorkerAsync(data);
    }

    private void BackWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        EcuData argumentData = e.Argument as EcuData;
        int x = 0;
        while (x<=10)
        {
            //
            // Code for reading in data from hardware.
            //
            argumentData.RPM = x;           //x is for testing only!
            argumentData.MAP = x * 2;       //x is for testing only!
            e.Result = argumentData;
            Thread.Sleep(100);
            x++;
       }
    private void BackWorker1_RunWorkerCompleted_1(object sender,  RunWorkerCompletedEventArgs e)
    {
        EcuData data = e.Result as EcuData;
        label1.Text = data.RPM.ToString();
        label2.Text = data.MAP.ToString();
    }
}

The above code just updated the GUI when backgroundworker is done with his job, and that's not what I'm looking for. 上面的代码只是在后台工作完成他的工作时更新了GUI,而这不是我正在寻找的。

You need to look at BackgroundWorker.ReportProgess . 您需要查看BackgroundWorker.ReportProgess

You can use it to periodically pass back an object to a method in the main thread, which can update the labels for you. 您可以使用它定期将对象传回主线程中的方法,该方法可以为您更新标签。

You can use a System.Threading.Timer and update the UI from the Timer's callback method by calling BeginInvoke on the main Form. 您可以使用System.Threading.Timer并通过调用主窗体上的BeginInvoke从Timer的回调方法更新UI。

uiUpdateTimer = new System.Threading.Timer(new TimerCallback(
            UpdateUI), null, 200, 200);

private void UpdateUI(object state)
{
    this.BeginInvoke(new MethodInvoker(UpdateUI));
}

private void UpdateUI()
{
    // modify labels here
}
class EcuData
    {
        public int RPM { get; set; }
        public int MAP { get; set; }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        EcuData data = new EcuData
        {
            RPM = 0,
            MAP = 0
        };
        BackWorker1.RunWorkerAsync(data);
    }

    private void BackWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        EcuData argumentData = e.Argument as EcuData;
        int x = 0;
        while (x<=10)
        {
            e.Result = argumentData;
            Thread.Sleep(100);
            this.Invoke((MethodInvoker)delegate
            {
                label1.Text = Convert.ToString(argumentData.RPM = x);           //send hardware data later instead, x is for testing only!
                label2.Text = Convert.ToString(argumentData.MAP = x * 2);       //send hardware data later instead, x is for testing only!
            });
            x++;
       }
    }

This works, but it is the correct way of doing it? 这有效,但这是正确的做法吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM