抱歉之前的糟糕表现。我编辑了代码,现在它给了我所需的结果。所以现在当一个线程在 richtextbox 中写入时,其他线程不会卡住。我不知道为什么我不需要在添加角色后刷新她的 richtextbox!但是,我仍然很困惑。有时当我不对任何控件使用 Invoke 方法时会出现错误,但现在,正如您在
中看到的那样panel.BackColor = Color.Red;
编译器没有提示。为什么?
namespace ThreadGUI
{
public partial class Form1 : Form
{
private Size s = new Size(50, 50);
Point p;
public Form1()
{
InitializeComponent();
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
p = new Point(e.X, e.Y);
Thread th = new Thread(new ThreadStart(DoWork));
th.Start();
}
public void DoWork()
{
Panel panel = new Panel();
Form1 frm = new Form1();
Point p1 = new Point(p.X - 25, p.Y - 25);
panel.Location = p1;
panel.Size = s;
panel.BackColor = Color.BlueViolet;
this.Invoke(new MethodInvoker(delegate { this.Controls.Add(panel); }));
Random ri = new Random();
while (true)
{
panel.BackColor = Color.BlueViolet;
int ti = ri.Next(500);
while (ti > 0)
{
int xi = ri.Next(2) * 10 - 5;
int yi = ri.Next(2) * 10 - 5;
Thread.Sleep(10);
p1.X += xi;
p1.Y += yi;
panel.Invoke(new MethodInvoker(delegate { panel.Location = p1; }));
ti--;
}
panel.BackColor = Color.Red;
lock ("jkj")
{
panel.BackColor = Color.Green;
string str = "I am a thread";
foreach (char c in str.ToCharArray())
{
richTextBox1.Invoke(new MethodInvoker(delegate { richTextBox1.AppendText(c.ToString()); }));
Thread.Sleep(100);
}
}
}
}
}
}
请您参考如下方法:
很抱歉成为坏消息的传播者,我没有冒犯的意思,但是发布的代码有各种各样的错误。 :(
首先,我不知道draw() 是做什么的,但如果它与UI 有任何关系,那么把它放在那里可能是错误的。它可能应该随着文本的更新在 UI 线程上执行。
其次,那些 Sleep() 方法调用在那里做什么?无论您想用它们完成什么,都有更好的方法。第二次调用似乎特别武断和有害。
第三,在持有任何类型的锁的同时调用 Control.Invoke() 是一个坏主意。这里没有明显的死锁,但这可能只是因为你没有发布一个好的代码示例,我们看不到导致死锁的部分。 Invoke() 调用本身本质上也是一个锁,因为在该方法返回之前没有其他代码会在 UI 线程上运行,因此与第一个锁一起设置可能的死锁(这听起来像是发生在你身上的事情)。
第四,不要调用Control.Refresh()。不需要。更新控件中的文本将导致控件变为“无效”,这将自动导致控件在适当的时间重绘。您不需要在这里匆匆忙忙,这样做可能会干扰您代码中的其他事情。
最后,我不明白规定的要求:您正在使用锁来防止多个线程更改文本。这正是 Invoke() 所做的!由于所有调用的委托(delegate)都在 UI 线程上执行,因此一次只能执行其中一个。因此,使用 Invoke() 已经必然会阻止多个线程同时更改文本。
换句话说,如果您添加 lock 语句的唯一原因是为了实现既定目标,则您不需要它。没有它,目标已经实现。
