如何在高速线程之间逐线程同步数据?

Posted

技术标签:

【中文标题】如何在高速线程之间逐线程同步数据?【英文标题】:How do I synchronize data between high-speed thread by thread? 【发布时间】:2021-09-14 11:50:46 【问题描述】:

在数据通信过程中出现错误,所以我问你一个类似的例子。

以下示例由发送线程和接收线程组成:

 private void Form1_Load(object sender, EventArgs e)
    
        t1 = new Thread(() => SendProc());
        t2 = new Thread(() => ReceiveProc());

        t1.Start();
        t2.Start();
    


    private void SendProc()
    
        while (true)
        
            buf = val.ToString();
            ++val;

            this.Invoke(new Action(delegate ()
            
                this.richTextBox1.Text = val.ToString() + "\n" + this.richTextBox1.Text;
                textBox1.Text = (++cnt1).ToString();
            ));

            Thread.Sleep(SEND_TIME_INTERVAL);
        

    



    private void ReceiveProc()
    

        while (true)
        
            if (string.IsNullOrEmpty(buf))
            
                Thread.Sleep(RECEIVE_TIME_INTERVAL);
                continue;
            

            this.Invoke(new Action(delegate ()
            
                this.richTextBox2.Text = val.ToString() + "\n" + this.richTextBox2.Text;
                textBox2.Text = (++cnt2).ToString();
            ));

            buf = "";
        
    

Left : Send Right : Receive

奇怪的是,发送数据和接收数据不同步。

Send proc 必须休眠 3 秒。

示例源代码: https://drive.google.com/file/d/1bqTyWdLViWw-glFztzYVoLah1egcZU7g/view?usp=sharing

如何解决这个问题?

【问题讨论】:

您需要使用事件、互斥体或类似的东西。此外,调用将同步到 UI 线程(您可能知道)——这将大大限制您的潜在吞吐量。最好使用缓冲区为 UI 排队,并且每隔一段时间才调用一次。 @500-InternalServerError 谢谢。关键是使用事件和互斥锁!不幸的是,我不知道我缺乏技能该怎么办......你有什么网站可以参考吗?即使我不使用 Invoke 方法打印 Log,结果也是相似的。 你必须提高你的 google 技能 :) 我刚刚做了这个搜索:msdn thread synchronization,第一个点击是Overview of synchronization primitives,这似乎很适合这个。 对于初学者,不要尝试从另一个线程修改 UI 线程。 .Invoke 阻塞并且根本不需要 @Panagiotis Kanavos 有没有办法在不使用 Invoke(不修改 UI 线程)的情况下同步更改的值? 【参考方案1】:

您可以使用BlockingCollection

var _items = new BlockingCollection<string>(10); // 10 is max buffered items
void SendProc() 
    for (int i = 0; i < 10000; i++) 
        _items.Add(i.ToString()); // blocks if more than 10 items not consumed
        Thread.Sleep(SEND_TIME_INTERVAL);
    
    _items.CompleteAdding();

void ReceiveProc() 
    while (!_items.IsCompleted) 
        var item = _items.Take(); // blocks if _items empty
        // this.Invoke(...); // use item
    

【讨论】:

很好的答案,除了使用IsCompleted 属性来控制执行流程。此属性并非真正用于此目的。使用BlockingCollection&lt;T&gt; 的正确(简单)方法是使用GetConsumingEnumerable 方法。 @GraphWalk 非常感谢!结果如下:drive.google.com/file/d/1Lu0P956sHSjFzxdOyEpFRkipfGnjWBgt/… @Theodor Zoulias 感谢您的回复 :)

以上是关于如何在高速线程之间逐线程同步数据?的主要内容,如果未能解决你的问题,请参考以下文章

线程同步和并发

Java线程同步问题产生的根源

java多线程有几种实现方法?线程之间如何同步

Java多线程——线程之间的同步

java多线程理解2

如何使进程与随机数量的活动线程同步?