【发布时间】:2015-12-21 18:46:19
【问题描述】:
我正在尝试做我的第一个多线程窗口表单应用程序,但我遇到了一个重要问题。 我知道我必须在我的线程中使用 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);
}
}
}
“win”是我的 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();
}
【问题讨论】:
-
Run方法是在后台线程还是 UI 线程上运行? -
附带说明,直接使用
Monitor.Enter和Monitor.Exit而不是lock语句是不寻常的,并且可能是个坏主意,除非您真的知道自己在做什么。例如,如果您在Enter和Exit之间的代码抛出异常,则该对象将处于锁定状态。 -
@adv12 我刚刚编辑了我的帖子我是如何运行我的线程的。 UI 线程正在运行方法,它正在创建和启动我的线程。
-
Program.loading()是做什么的? -
基本上你所做的是停止为拥有表单的线程处理消息的消息循环。 BeginInvoke 通过向该线程发布消息来工作,该消息最终由该消息循环处理。当您执行 Console.ReadKey 时,一切都停止工作,与线程或 begininvoke 无关,尽管它们是相同问题的受害者。此外,您应该将 async/await 视为完全多线程编程的替代方案,它有些不同,而且比较容易。
标签: c# multithreading winforms invoke begininvoke