从另一个线程更改控件文本的正确方法

时间:2020-05-14 14:03:54

标签: c# multithreading winforms

我有这个线程从5倒数到0:

public static int seconds = 5;
        public static void startTimer()
        {
            Thread thread = new Thread(() =>
            {
                while (seconds > 0)
                {
                    Thread.Sleep(1000);
                    seconds--;
                }                
            });
            thread.IsBackground = true;
            thread.Start();
        }

我想将标签“ label1”的文本值更新为我的主表单“ Form1”上剩余的秒数,

我目前正在线程内使用它:

Application.OpenForms["Form1"].Controls["label1"].Invoke(new Action(() => Application.OpenForms["Form1"].Controls["label1"].Text = str));

什么是正确的方法, 我需要为任务创建一个自定义线程。

这样是正确的吗?如果不是,如何从线程中引用label1的text属性。

1 个答案:

答案 0 :(得分:2)

您可以捕获正确的调度程序并将其传递给线程,如下所示:

    private void button1_Click(object sender, EventArgs e)
    {
        int seconds = 5;

        var dispatcher = Dispatcher.CurrentDispatcher;

        Task.Run(async () => 
        { 
            while(seconds > 0)
            {
                await Task.Delay(1000);
                seconds--;
                dispatcher.Invoke(() => textBox1.Text = seconds.ToString());                                        
            }
        });
    }

在没有调度员的情况下,可以这样做:

    private void button1_Click(object sender, EventArgs e)
    {
        int seconds = 5;

        ISynchronizeInvoke invoker = this;

        Task.Run(async () => 
        { 
            while(seconds > 0)
            {
                await Task.Delay(1000);
                seconds--;
                Action updateMethod = () => textBox1.Text = seconds.ToString();
                invoker.Invoke(updateMethod, new object[] { });
            }
        });
    }