为什么当线程启动时,窗体崩溃?线程安全吗?

Why when thread starts, the form crashes?Is Thread-safe?

我有一个游戏有 90 个灰色数字,并且周期性地,其中一些会变成蓝色。(已简化!)

现在我使用: Game-->Timer-->Thread-->coloring numbers 因为我也想在着色数字时使用我的游戏。

代码:

some variables..
public FormHome()
    {
        InitializeComponent();

        TEstrazione = new System.Timers.Timer(10000);
        TEstrazione.AutoReset = false;
        TEstrazione.Elapsed += timerEstrazioneElapsed;
        TEstrazione.Start();
    }
private void timerEstrazioneElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            ThreadEstrazione = new Thread(cThread);
            ThreadEstrazione.IsBackground = true;
            ThreadEstrazione.Start();
        }
 private void cThread()
        {          
//other methods that change others controls..   
                coloring();    
                TEstrazione.Start();
            }
 void coloring()
        {
            for (int i = 0; i < 20; i++)//20 numbers to make colored
            {
                int num = *get random number*;
                Label lbl;
                lbl = (Label)panelNumembers.Controls["n" + num.ToString()];

            if (lbl.InvokeRequired)
            {
                lbl.Invoke(new Action(coloring), new object[] { });
                return;
            }

            lbl.BackColor = Color.DodgerBlue;
            lbl.ForeColor = Color.Navy;
            lbl.Refresh();
            Thread.Sleep(800);
        }
    }

对不起,如果有些名字是意大利语,但我认为它们并不重要。
问题是,当线程为标签着色时,程序锁定:我无法按下按钮甚至无法关闭它!
我认为这是一个线程安全的问题,但我不认为知道其他方法。

正如我所写,cThread 中还有其他方法,所有更改控件。其中之一是:

void refreshLabel()
                { 
//here I always used one of the controls for the InvokeRequired
     because in some cases I have so many and if I do the InvokeRequired 
    for each control becomes too long the code
                    if (label1.InvokeRequired) 
                    {
                        ne.Invoke(new Action(refreshLabel), new object[] { });
                        return;
                    }           
             label1.Text = "xxxxx"; 
             label1.Refresh();
             label2.Text = "xxxxxxxxxxxxxxxx";      
             label2.Refresh();
                }   

总而言之,我有很多由cThread启动的方法,改变了很多控件,有没有一种方法可以使其线程安全而不需要拉伸太多代码?
我为英语道歉,但我是意大利人,用另一种语言解释问题并不容易。

我正在使用我女朋友的笔记本电脑,所以我会编辑我的答案并尽快给你一个更好的答案。出现问题是因为大部分执行都在 UI 线程中。您应该在后台执行大部分执行。当您想更新 UI 时,您需要将上下文更改为 UI 线程(仅更新!)。

将颜色更改为:

void coloring()
{
    for (int i = 0; i < 20; i++)//20 numbers to make colored
    {
        int num = *get random number*;
        Label lbl;
        lbl = (Label)panelNumembers.Controls["n" + num.ToString()];

    var updateUI = new Action(() => {

    lbl.BackColor = Color.DodgerBlue;
    lbl.ForeColor = Color.Navy;
    lbl.Refresh();
    });

    if (lbl.InvokeRequired)
    {
        Invoke(updateUI);
    }
    else
    {
        updateUI();
    }
    Thread.Sleep(800);
}

如果您的代码中没有其他阻塞操作,那么这可能有效