C#WPF与WinForm使用多线程调用硬件设备且不会卡顿界面的操作方法(保证线程安全)

1.背景:有30台TCP设备需要同时建立套接字,并且需要一键对它们进行各种操作(传统单线程方法会导致界面长时间卡住,不能点击,且不会有实时信息返回)。

2.如何创建一个新的线程,与使用委托的方法直接传参与调用函数:

Thread thr = new Thread(())//创建单个线程
thr.Start();//启动

Thread n = new Thread(new ThreadStart(() => MyCode(a)));//使用委托并传递参数的写法
Thread n = new Thread(() => MyCode(a));//此为上行代码的简写

3.建立多个插座就是在全局先声明,等传入IP端口等数据后再赋值给它们,下面简单写个例子:

Socket sc1;
Socket sc2;

private void Button连接_Click(object sender, RoutedEventArgs e)
        {
            string sum = TBIP1.Text.Trim() + "," + TBIP2.Text.Trim();
            string[] arr = sum.Split(',');
            String IP1 = arr[0];
            String IP2 = arr[1];
            Thread thr1 = new Thread(() => Con(1, IP1));
            Thread thr2 = new Thread(() => Con(2, IP2));
            thr1.Start(); thr2.Start(); 
        }

private void Con(int ID, string IP)
        {
            if (IP != "")
            {
                try
                {
                    switch (ID)
                    {
                        case 1:
                            sc1 = ScanCtrl.Connect(IP, 4001, 1000);
                            bool flag1 = sc1.Connected;//根据设备返回值判断是否连接成功
                            if (flag1)
                            {
                                Conputsuc(ID);
                            }
                            else
                            {
                                Conputfalse(ID);
                            }
                            break;
            //剩余部分省略了
}}}}

设备是否连接成功肯定是要提供反馈的,如果在上面代码的ConPutSuc(ID);处写对界面的操作的话会跨线程,如AppendText通过,会不允许操作,因为规定界面的操作必须在主线程完成,解决方案在第4条。

4.把操作转回到主线程,也就是我的ConPutSuc(ID);方法,使用Dispatcher.Invoke(new Action(()=> {//你的代码})):

private void Conputsuc(int ID)
        {
            Dispatcher.Invoke(new Action(() =>
            {
                TB信息.AppendText(ID + "号设备,连接成功!" + DateTime.Now + "\r\n");
                TB信息.ScrollToEnd();
            }));
        }

如果是winform应用,是没有Dispatchar.Invoke的,可以使用BeginInvoke。

5.如果两个线程都操作了我的精读函数,肯定会导致输出顺序是随机的,或者有可能直接导致内部数据错乱,有很多种方法,这里就先忽略性能和线程独立,使用一种简单的方法来处理,就是给多线程操作的这一块内存或者说方法加锁,方法如下:

private object MyLock = new object();//先在外部创建一个锁对象

private void Con(int ID, string IP)
        {
            lock (MyLock)
            {
                //需要锁住的代码
            }
        }


这样锁住之后这块代码一次只能被一个线程操作,其它的先排队。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值