C# 勇哥关于多线程读写plc内存的研究续,长期间运行出现的若干问题的研究

勇哥注:

我们继续上一篇C# 勇哥关于多线程读写plc内存的研究续,引用ReaderWriterLockSlim锁带来的读操作并发的问题


此系列贴子已经写了好几篇了:

(4)C# 勇哥关于多线程读写plc内存的研究续,引用ReaderWriterLockSlim锁带来的读操作并发的问题

http://www.skcircle.com/?id=1995

(3)C# 勇哥关于多线程读写plc内存的研究续,解决UI控件读写的效率问题

http://www.skcircle.com/?id=1985

(2)C# 勇哥关于多线程读写plc内存的研究续,解决lock锁的效率问题

http://www.skcircle.com/?id=1983

(1) C# 勇哥关于多线程读写plc内存的研究

http://www.skcircle.com/?id=1981


上一篇末尾的问题:

跑了一晚上后,发现只有最后一个地址的数值(13414)在跳动,其它的都不动,应该是死掉了。

image.png


首先勇哥检查了plc的内存,发现头三个地址的值确实没有更新了,只有最后一个地址的值在变化。

这说明“启动4个读线程”没有问题,并不是因为它们死掉了所以ui上刷新不了。

再看下其中一个写线程的代码:

  PlcReadWrite plc = null;
            Random ran = null;
           
            Task.Factory.StartNew(() =>
            {
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                short j1 = 0;
                while (!rndStop)
                {
                    plc = new PlcReadWrite();
                    ++j1;
                    plc.Write(0,j1, Guid.NewGuid());
                    while(true)
                    {
                        if(sw1.ElapsedMilliseconds>1000)
                        {
                            sw1.Restart();break;
                        }
                        Thread.Sleep(10);
                    }
                }
            });

首先那个j1是个short,最大值为32767,所以并不是因为j1溢出了。

由数值6717来看,第一个地址写内存是每隔1秒写一次,也就不到2小时,上面的代码就死掉再不工作了。

地址1--地址4,依次是隔1, 2, 3, 4秒写入

但是最后一个地址值反而最大,这让人怀疑是否写入混乱了。


我们干脆加把锁,让4个写入无可能同时写入。(虽然4个时序按时序来讲好像是不能同时写入的)

这个锁定义如下:

private static readonly object writeLock = new object();


只需要lock到Write函数里就行了。

现在这个函数就有两把锁了。

       /// <summary>
        /// 写plc内存
        /// </summary>
        /// <param name="addr">plc内存地址,填写相对地址,从0开始</param>
        /// <param name="data">写入的数据,short类型</param>
        /// <param name="_id">guid</param>
        /// <returns></returns>
        public int Write(int addr,short data, Guid _id)
        {
            lock (writeLock)
            {
                rwlock.EnterWriteLock();
                {
                    try
                    {

                        var writeSw = new Stopwatch();
                        writeSw.Start();
                        isRead = false;
                        WriteCmdList.Add(new WriteCmd()
                        {
                            addr = addr,
                            id = _id,
                            writeData = data,
                            writeStatus = -1
                        });
                        var idx = -1;
                        int js1 = 0;
                        while (true)
                        {
                            if (writeSw.ElapsedMilliseconds > 2000)
                            {
                                //读plc超时
                                writeSw.Stop(); return -1;
                            }
                            if (sw2.ElapsedMilliseconds > 50 && js1 == 0)
                            {
                                //通知写plc
                                mr[0].Set(); sw2.Restart(); ++js1;
                            }
                            idx = WriteCmdList.FindIndex(s => s.id == _id && s.writeStatus == 1);
                            if (idx >= 0)
                            {
                                //写成功了,返回1
                                WriteCmdList.RemoveAt(idx);
                                plclog.AddLog(new logdata()
                                {
                                    id = _id,
                                    readOrWrite = readwriteEnum.write,
                                    plcAddr = (short)addr,
                                    recTime = DateTime.Now,
                                    itemCount = WriteCmdList.Count
                                });
                                return 1;
                            }
                            Thread.Sleep(1);
                        }
                    }
                    finally
                    {
                        rwlock.ExitWriteLock();
                    }
                }
            }
        }


由于至少要测试2小时以上才可能看到结果。

就留今天晚上跑通宵吧。



未完待续。。。。



--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!





本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年5月    »
12345
6789101112
13141516171819
20212223242526
2728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864