简体   繁体   English

C#中的多线程使用锁

[英]Multithreading in C# using lock

sorry for the bad presentation before. 对不起以前的糟糕演示。 I edited the code and now it gives me the required result. 我编辑了代码,现在它给了我所需的结果。 So now when a thread writes in the richtextbox, the other threads do not freeze. 所以现在当一个线程在richtextbox中写入时,其他线程不会冻结。 I don't know whey I don't need to refresh the richtextbox her after adding a character! 我不知道在添加角色后我不需要刷新她的richtextbox! However, I'm still confused. 但是,我仍然感到困惑。 Sometimes when I don't use Invoke method with any control I got an error, but now, as u can see in 有时当我不使用任何控件的Invoke方法时我得到了一个错误,但是现在,正如你所看到的那样

panel.BackColor = Color.Red;

The compiler did not complain. 编译器没有抱怨。 Why? 为什么?

    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);
                    }
                }
            }
        }
    }
}

Sorry to be the bearer of bad news, and I mean no offense, but the posted code is all kinds of wrong. 很抱歉成为坏消息的持有者,我的意思是没有冒犯,但发布的代码是各种错误的。 :( :(

First, I don't know what draw() does, but if it has anything to do with the UI, it's probably wrong to put it there. 首先,我不知道draw()作用,但是如果它与UI有关,那么把它放在那里可能是错误的。 It probably should be executed on the UI thread along with the update of the text. 它可能应该在UI线程上执行以及更新文本。

Second, what are those Sleep() method calls doing there? 第二,那些Sleep()方法调用在那里做什么? Whatever you're trying to accomplish with them, there is a better way. 无论你想用它们做什么,都有更好的方法。 The second call seems particularly arbitrary and harmful. 第二次电话似乎特别武断和有害。

Third, it is a bad idea to ever call Control.Invoke() while holding any kind of lock. 第三,在持有任何类型的锁时调用Control.Invoke()是个坏主意。 There is no obvious deadlock here, but that may be just because you haven't posted a good code example and we can't see the part that's causing the deadlock. 这里没有明显的死锁,但这可能只是因为你没有发布一个好的代码示例,我们无法看到导致死锁的部分。 The Invoke() call itself is essentially a lock as well, as no other code will run on the UI thread until that method returns, and so that along with the first lock set you up for a possible deadlock (which is what sounds like is happening to you). Invoke()调用本身也是一个锁,因为在该方法返回之前,UI线程上不会运行任何其他代码,因此与第一个锁一起设置可能的死锁(这听起来像是发生在你身上)。

Fourth, don't call Control.Refresh() . 第四,不要调用Control.Refresh() It's not needed. 这不是必需的。 Updating the text in the control will cause the control to become "invalidated", which will automatically result in the control being redrawn at an appropriate time. 更新控件中的文本将导致控件变为“无效”,这将自动导致控件在适当的时间重绘。 You don't need to hurry things along here, and doing so may wind up interfering with other things in your code. 你不需要在这里赶快行动,这样做可能会干扰你代码中的其他事情。

Finally, I don't understand the stated requirement: that you are using the lock to prevent more than one thread from changing the text. 最后,我不明白规定的要求:您正在使用锁来防止多个线程更改文本。 That's exactly what Invoke() will do! 这正是Invoke()将要做的! Since all invoked delegates are executed on the UI thread, only one of them can execute at a time. 由于所有调用的委托都在UI线程上执行,因此一次只能执行其中一个委托。 So using Invoke() already necessarily prevents more than one thread from changing the text at a time. 因此,使用Invoke()必然会阻止多个线程一次更改文本。

In other words, if the only reason you added the lock statement was to accomplish that stated goal, you don't need it. 换句话说,如果添加lock语句的唯一原因是为了实现所述目标,则不需要它。 The goal is already accomplished without it. 没有它,目标已经完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM