为什么当线程启动时,表单崩溃?是否是线程安全的?

时间:2015-02-15 17:16:26

标签: c# forms thread-safety label

我有一个有90个灰色数字的游戏,并且定期会有一些变成蓝色。(简化!)

现在我使用: 游戏 - >计时器 - >线程 - >着色数字 因为我想在着色时使用我的游戏。

代码:

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启动的方法可以改变很多控件,有一种方法可以让线程安全而不会拉伸太多的代码吗?
我为英语道歉,但我是意大利语,并不容易用另一种语言解释问题。

1 个答案:

答案 0 :(得分:0)

我正在使用我女朋友的笔记本电脑,所以我会编辑我的答案并尽快给你一个更好的答案。出现问题是因为大多数执行都在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);
}

如果您的代码中没有其他阻止操作,那么这可能会起作用