c# 多线程调用dll出现错乱

landcloud 2017-04-27 08:26:46
手头一个项目,目标是轮询n台考勤机,实时获取打卡信息并处理,考勤机的二次开发包是一个dll,无源码,不清楚是否是线程安全的。我的做法是每台机器开一个线程轮询。每个线程按考勤机二次开发包说明先opennet---》绑定对应考勤机ip--》轮询--》如有考勤信息处理之。实际写好了发现单线程无问题,多线程时候只有最后一个执行线程对应的考勤机可以收到消息,其余的完全失效。目前采用的笨办法是写脚本开了多个进程,每个进程对应一台机器,但是写日志什么的比较麻烦。请问有没有简单些的方法能多线程处理这种情况,dll导入后方法都是static的,感觉直接在线程里用会有问题。请懂的大大赐教
...全文
451 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
敌敌畏耶 2017-09-01
  • 打赏
  • 举报
回复
考虑多进程试试
大然然 2017-09-01
  • 打赏
  • 举报
回复
这个场景为什么一定要多线程访问呢? 一个个挨个访问不就是了? 无非就是访问--处理--入库 操作,会很耗时吗?
雪狼孤竹 2017-09-01
  • 打赏
  • 举报
回复
不清楚你的考勤机与PC间是以什么方式通讯,是否是多个考勤机在PC端只是一个接口。 假如是类似于串口的通讯,建议你对串口的操作,不要频繁的开关。 把开关放在处理的两端。多个设备的处理也应该如此,在第一个处理前打开,在最后一个处理后关闭。
cyg17173 2017-08-31
  • 打赏
  • 举报
回复
汗,高人啊。 自己小号发帖,大号回帖拿分。 请开始你的表演。
  • 打赏
  • 举报
回复
你启动线程,然后线程中弄一个死循环,然后死循环中又只不过是立刻要 BeginInvoke,然后又 Sleep,然后 beginInvoke 注册的代码中又有死循环。这个过程完全是自己捆绑自己啊。 删除坑人的“循环+Sleep” 语句,每一个线程执行的代码应该是瞬间的、几十毫秒就结束的。并且只有操作界面控件时才需要 BeginInvode(而不是把与控件无关的代码也放到 BeginInvoke中)。
  • 打赏
  • 举报
回复
什么叫做“每台机器开一个线程轮询”啊?一个 for 循环轮询各个设备,跟线程有什么关系?
LGQ2017 2017-08-31
  • 打赏
  • 举报
回复
private void Cmd_GetPos_Click(object sender, EventArgs e) { if (GetPos_iCount % 2 == 0) { GetPosBool = true; CommOpen_nCid = OpenComm(1); if (CommOpen_nCid >= 0) { CommClose_nCid = -1; newthread= new Thread(crossThread); newthread.IsBackground = true; newthread.Start(); } else { Ms_BscCloseComm(CommOpen_nCid); CommBool = false; } } else { GetPosBool = false; } GetPos_iCount++; } private void crossThread() { CommBool = true; while (GetPosBool) { if(!newthreadpuse){getposfunction();} Thread.Sleep(1000); } } private void getposfunction() { if (textBox_GetPos_X.InvokeRequired) { delegatefunction getpos_delegate = new delegatefunction(getposfunction); BeginInvoke(getpos_delegate); } else { short rc; rc = GetPos(CommOpen_nCid, out P_var[0]);//第三方DLL中的方法 if (rc == 0) { textBox_GetPos_X.Text = Convert.ToString(P_var[0]); } else { richTextBox1.AppendText("GetPos failure>>"); } CommClose_nCid = CloseComm(CommOpen_nCid); while (true) {if (CommClose_nCid == 0) { break; } } CommBool = false; } } getposfunction()方法中的代码执行需要250ms左右; 当在主程序里面点击按钮事件时,会使newthreadpuse变为true,然后等待getposfunction()结束后, CommClose_nCid = CloseComm(CommOpen_nCid); CommClose_nCid为0时,控件才能调用DLL中的方法, 因为必须先调用 OpenComm();方法建立通讯,而后才能调用DLL中的方法,调用其中的方法之后再调用CommClose()方法关闭通讯,如此循环。 这是我第一次尝试的方法,再newthread开启的时候点击主线程中其它控件经常会卡死(但不是每次都卡死); 所以我就把跨线程调用控件检查关闭了,Control.CheckForIllegalCrossThreadCalls = false; 然后将getposfunction()内的代码转移到crossthread中,直接进行循环调用,结果出现了调用方法响应太慢,近乎卡死的现象。
xian_wwq 2017-04-28
  • 打赏
  • 举报
回复
如果非线程安全,就需要自行加锁, 这样一来多线程就变成了串行操作 lz把连接代码贴出来看看
xuggzu 2017-04-27
  • 打赏
  • 举报
回复
一般像这种设备的dll都是C++写的,代码一般也都是些存储读写和端口读写操作,理论上不应该有线程不安全之说。而且楼主的线程是一线程对一设备,所以线程间对设备的操作部分代码不会有冲突,能引起线程不安全的肯定都是楼主线程里面共享操作代码。 因此,只有最后一个设备能出数,估计是: 1、楼主代码有不合理的因素; 2、不完全排除设备dll里特殊的机制导致问题,当然这种可能性很小。

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧