为什么当线程启动时,窗体崩溃?线程安全吗?
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);
}
如果您的代码中没有其他阻塞操作,那么这可能有效
我有一个游戏有 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);
}
如果您的代码中没有其他阻塞操作,那么这可能有效