Skip to main content
 首页 » 编程设计

c#之C#中的多线程使用锁

2024年08月06日44pander-it

抱歉之前的糟糕表现。我编辑了代码,现在它给了我所需的结果。所以现在当一个线程在 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 语句的唯一原因是为了实现既定目标,则您不需要它。没有它,目标已经实现。