调用冻结我的Windows窗体
本文关键字:窗体 Windows 我的 冻结 调用 | 更新日期: 2023-09-27 18:27:42
我正在尝试我的第一个多线程windows表单应用程序,但我遇到了一个重要问题。我知道我必须在线程中使用Invoke或BeginInvoke来更改表单中的RichTextBox,但当我尝试这样做时,我的UI只是冻结了,而控制台正在正确打印我的结果。
class MyThread
{
public MyThread()
{
}
public void Run()
{
byte[] tmp;
while (true)
{
// lock (sem1)
Monitor.Enter(sem1);
{
if (end)
{
Monitor.Exit(sem1);
break;
}
tmp = inp.ReadNr();
if (inp.End())
end = true;
}
if(inOrder)
Monitor.Enter(sem2);
Monitor.Exit(sem1);
bool p = CSL.checkNr((byte[])tmp.Clone());
Monitor.Enter(sem3);
if(inOrder)
Monitor.Exit(sem2);
{
outp.WriteNr(tmp, p);
//win.richTextBox2.AppendText(String.Join("", tmp) + ''n');
win.richTextBox2.BeginInvoke(new Action(delegate ()
{
win.richTextBox2.AppendText("wtf");
}));
}
Monitor.Exit(sem3);
}
}
}
"胜利"是我班Form1的目标。我无法应付…
编辑:
static public void loading()
{
outp = new oFile();
Thread[] thr = new Thread[nrThreads];
for (int a = 0; a < nrThreads; a++)
new Thread(new ThreadStart(new MyThread().Run)).Start();
//new MyThread().Run();
Console.ReadKey();
}
形式:
private void button1_Click(object sender, EventArgs e)
{
Program.loading();
}
这里的问题是Program.loading
:中的这一行
Console.ReadKey();
这会使主GUI线程停止运行,所以让我们看看现在发生了什么:
- 发布到主GUI线程的消息将不会得到处理(因为您不会返回到消息循环)
- 来自不同线程的BeginInvoke不会被处理,因为它们的工作方式是将消息发布到主GUI线程正在处理的同一消息队列(现在已经停止)
- 直到你按下一个键(假设这是可能的),一切都会停止。您会注意到,表单中的绘画消息不会得到处理,最终表单会淡出并显示"已停止响应"文本
因此,删除这行代码,至少你的程序不应该像以前那样停滞不前。
话虽如此,我敦促你从一开始就尝试更简单的例子。您对多个监视器的交错、手动处理让我认为您正处于学习多线程编程的初级阶段,并且已经开始使用一些复杂的齿轮,这些齿轮需要非常准确地互锁才能正确工作。
相反,我想让您看看async / await
,它是在C#5中添加的用于处理异步编程的新关键字。尽管异步和多线程不是一回事,也不意味着两者都是另一回事,但异步编程通常会让你在很大程度上获得一个响应UI,它不会在等待时冻结。