AutoResetEvent和Queue在线程用的使用

//类型简介
AutoResetEventWindow 类:UI窗体
Port类:一个模拟串口的类型
Sender类:数据包

//成员简介
Port.ReceiveEvent:一个事件成员,模拟串口收到数据后通过事件触发一个回调
Port.Write():一个模拟串口写入数据的方法

程序运行思路
1、在UI窗体类中声明一个队列queue,用于存储下包数据包Sender的实例
2、在UI窗体类中声明一个producer线程,用于不断向队列queue中新增sender
3、在UI窗体类中声明一个customer线程,用于不断从队列queue中取出sender
4、将取出来的sender数据包下发给串口,然后利用AutoResetEvent 阻塞当前线程,直至在Port.ReceiveEvent事件的回调函数中松开阻塞器,再取出下一个sender发给串口…
5、如此循环…
6、可以通过按钮事件随时向队列queue中插入sender…(插队)

namespace WPF大全.View
{
    /// <summary>
    /// 发送对象
    /// </summary>
    public class Sender
    {
        public string Text = "";
        public AutoResetEvent Auto = null;
        public bool IsSuccess { get; internal set; }
    }
    public class Port
    {
        public event Action<Sender> ReceiveEvent;
        public void Write(Sender sender)
        {
            Thread.Sleep(500);
            sender.IsSuccess = true;
            sender.Text = "已接收:" + sender.Text;
            ReceiveEvent?.Invoke(sender);
        }
    }
    /// <summary>
    /// AutoResetEventWindow.xaml 的交互逻辑
    /// </summary>
    public partial class AutoResetEventWindow : Window
    {
        private Thread producer;
        private Thread customer;

        private Queue<Sender> queue = new Queue<Sender>();
        private object queueLock = new object();
        private AutoResetEvent Auto = new AutoResetEvent(false);

        Port port = new Port();

        public AutoResetEventWindow()
        {
            InitializeComponent();
            port.ReceiveEvent += Port_ReceiveEvent;
            producer = new Thread(Product);//生产者
            producer.IsBackground = true;
            producer.Start();
            customer = new Thread(Custom);//消费者
            customer.IsBackground = true;
            customer.Start();

        }

        //回调函数中解析回传数据,并设置AutoResetEvent.Set()
        private void Port_ReceiveEvent(Sender obj)
        {
            Dispatcher.Invoke(() =>
            {
                _richTextBox.AppendText("\n");
                _richTextBox.AppendText(obj.Text);
                _richTextBox.ScrollToEnd(); //自动滚动到底
                Auto.Set();
            });
        }

        /// <summary>
        /// 消费者线程
        /// </summary>
        private void Custom()
        {
            while (true)
            {
                Sender item = null;
                lock (queueLock)
                {
                    if (queue.Count > 0)
                    {
                        item = queue.Dequeue();
                    }
                }
                if (item != null)
                {
                    port.Write(item);
                    Auto.WaitOne();
                }
                Thread.Sleep(100);
            }
        }

        /// <summary>
        /// 生产者线程
        /// </summary>
        private void Product()
        {
            while (true)
            {
                Sender sender = new Sender();
                sender.Auto = this.Auto;
                sender.Text = DateTime.Now.ToString();
                lock (queueLock)
                {
                    queue.Enqueue(sender);
                }

                Thread.Sleep(1000);
            }
        }

        //偶尔手动生产
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Sender item = new Sender();
            item.Auto = this.Auto;
            item.Text = $"插入:{DateTime.Now.ToString()}";
            lock (queueLock)
            {
                queue.Enqueue(item);
            }
        }
    }
}

前端XAML代码

<Window x:Class="WPF大全.View.AutoResetEventWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF大全.View"
        mc:Ignorable="d"
        Title="AutoResetEventWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0">
            <Button Content="插入一条消息" Margin="10" Click="Button_Click"/>
        </StackPanel>
        <RichTextBox Grid.Column="1" x:Name="_richTextBox"/>

    </Grid>
</Window>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值