共享COM口的抢占冲突问题

viki117 2010-07-21 10:13:46
最近来了一套设备,可以把接在它链路上的设备,分享到其他设备上,我把一个COM口转USB接口,插到网络中,那么在2台电脑上都发现了这个COM设备;

用SerialPort类作了一个COM口的Write程序,可是问题来了,当2台电脑同时访问这个COM口的时候,2个程序都报错,提示COM口被占用中,之后,就一直提示被占用中,关闭程序,再开启,还是提示被占用,只有一台电脑把这个COM卸载了,才可以解开占用状态;

我想这种情况很多人没有遇到过,这个情况的关键是,COM设备实际是一个设备,但是通过共享网络,分享到2台电脑上,在2台电脑上出现了该设备,在2台电脑看来,这个COM就成了2个设备;这种状态和单机上多个程序访问COM口不一样,所以一直找不到方法解决,想找各位大侠提供点帮助,思路也行。。。可能也和USB转COM的驱动有关

...全文
630 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
viki117 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 yyd021 的回复:]
引用 12 楼 viki117 的回复:
引用 11 楼 wuyazhe 的回复:
其实串口本身是可以共享使用的,但驱动已经由微软实现成独占方式读写的。共享读写要用apihook或更改驱动。而且共享是很麻烦的,比如同一个串口,收到1234567890,第一个执行ReadExisting读了123的时候,另一个进程开始执行ReadExisting吧后面的读了几个字节,这种情况在2个进程操作甚至多……
[/Quote]
2台电脑既能同时操作设备,又各自具有独立性,互不依赖,问题就出在里,但是实际是一个设备,而2台电脑都把这个设备当作它自己的独享设备,当2台电脑以前要COM的时候,问题就来了,理论上的东西,在这种情况下就乱了
yyd021 2010-07-27
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 viki117 的回复:]
引用 11 楼 wuyazhe 的回复:
其实串口本身是可以共享使用的,但驱动已经由微软实现成独占方式读写的。共享读写要用apihook或更改驱动。而且共享是很麻烦的,比如同一个串口,收到1234567890,第一个执行ReadExisting读了123的时候,另一个进程开始执行ReadExisting吧后面的读了几个字节,这种情况在2个进程操作甚至多个电脑操作的情况下就很难互斥,并发无法控制,……
[/Quote]
应该不至于出现互相锁死的情况吧,顶多是后面的那台电脑不能连接到串口。
这种情况我以前也经常遇见,是一台电脑同时与2个串口设备通讯,设备返回数据的时候出现错误的。像你这样电脑上出现错误应该好解决一点。
1.修改软件的连接函数,加入try...catch.. ,当发现串口错误时停止连接,转为向另外一台电脑发送命令,由另外一台已经连接上设备的电脑代为处理。并返回数据。
2.可以在软件中连接串口时,增加一个线程,用来处理其他软件发来的数据,代为传输数据(相当于短时间内提供串口服务),并返回处理值。
这样,2台电脑既能同时操作设备,又各自具有独立性,互不依赖。
viki117 2010-07-27
  • 打赏
  • 举报
回复
继续顶,虚拟不也还是一个COM,已经被占用了,再虚拟,还是被占用,2台电脑谁都不释放..
viki117 2010-07-21
  • 打赏
  • 举报
回复
你可以去搜索下DIIVA,大概知道背景了~~
其实不管什么硬件,要改硬件都是很困难的事,软件可以搞定当然是首选
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 hyblusea 的回复:]
引用 9 楼 viki117 的回复:
引用 8 楼 hyblusea 的回复:
你的共享方式不对。 COM能同时被两个程序访问吗? 要么转为以太网

都说了,新进的设备,这套设备就有怎么强大,所有插在它共享USB上的设备,都可以共享


唉...你这设备再强大,又有什么用?能共享,但同样不支持多客户访问,有用吗?你买错设备了, 还有更强大的.
Google搜一下Nport
[/Quote]

不讨论设备了,只是想知道怎么解决问题~~软件方面
hyblusea 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 viki117 的回复:]
引用 8 楼 hyblusea 的回复:
你的共享方式不对。 COM能同时被两个程序访问吗? 要么转为以太网

都说了,新进的设备,这套设备就有怎么强大,所有插在它共享USB上的设备,都可以共享
[/Quote]

唉...你这设备再强大,又有什么用?能共享,但同样不支持多客户访问,有用吗?你买错设备了, 还有更强大的.
Google搜一下Nport
showjancn 2010-07-21
  • 打赏
  • 举报
回复
1:COM关掉了也提示被占用。
解决方法,由于.net回收机制,可能不是立即回收。所以要强制垃圾回收。即:Close后调用强制回收。
2:串口占用。
丛硬件上说没办法解决,一个串口打开了,就不可能被别一个实例使用。
但可以通过虚拟方式来进行。比如从COM1虚拟出COM2,COM3。这时你两台机器再对COM2、COM3进行操作。
类似的软件有如:GPS Gate,
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 wuyazhe 的回复:]
我比较赞同zgke的做法。
你描述的现象,共享,那其实已经是做了一层转换了。
[/Quote]
那样就要一个服务器了,不现实阿。。。。
他的转换是物理层上的,通过USB接口,模拟硬件,所以和直接把USB插本机区别不大,只是中间的通信需要他自己实现
兔子-顾问 2010-07-21
  • 打赏
  • 举报
回复
我比较赞同zgke的做法。
你描述的现象,共享,那其实已经是做了一层转换了。
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wuyazhe 的回复:]
其实串口本身是可以共享使用的,但驱动已经由微软实现成独占方式读写的。共享读写要用apihook或更改驱动。而且共享是很麻烦的,比如同一个串口,收到1234567890,第一个执行ReadExisting读了123的时候,另一个进程开始执行ReadExisting吧后面的读了几个字节,这种情况在2个进程操作甚至多个电脑操作的情况下就很难互斥,并发无法控制,谁都读不完整。除非底层缓存数据,每个连接的程……
[/Quote]
我暂时不需要读,只要写就好了,不知道有没有方法,不出现COM被占用,最少也要能强制释放掉,现在的情况是2边一起写,结果2边一起提示被占用,然后就开始互相锁死,必须有一方卸载掉该设备
兔子-顾问 2010-07-21
  • 打赏
  • 举报
回复
其实串口本身是可以共享使用的,但驱动已经由微软实现成独占方式读写的。共享读写要用apihook或更改驱动。而且共享是很麻烦的,比如同一个串口,收到1234567890,第一个执行ReadExisting读了123的时候,另一个进程开始执行ReadExisting吧后面的读了几个字节,这种情况在2个进程操作甚至多个电脑操作的情况下就很难互斥,并发无法控制,谁都读不完整。除非底层缓存数据,每个连接的程序给一个副本。这样就是重写驱动了。。。
可能有更好方法。我就不知道了。
viki117 2010-07-21
  • 打赏
  • 举报
回复
可以直接通过你电脑出一根USB线,连接到他的网络中,然后就可以通过这条USB链路,分享网络中任何可共享的设备
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 hyblusea 的回复:]
你的共享方式不对。 COM能同时被两个程序访问吗? 要么转为以太网
[/Quote]
都说了,新进的设备,这套设备就有怎么强大,所有插在它共享USB上的设备,都可以共享
hyblusea 2010-07-21
  • 打赏
  • 举报
回复
你的共享方式不对。 COM能同时被两个程序访问吗? 要么转为以太网
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hyblusea 的回复:]
解决方法很多:
1.串口转以太网的设备,比如Nport,将串口数据,以UDP方式广播到到多个客户端

2.采用服务器/客户端, 服务端负责与串口设置交互, 服务端与客户端进行通讯
[/Quote]
不考虑服务器模式,因为是通过物理链路共享,中间加个服务器,要共享做什么?一条网线全搞定。。
这个共享就是设备无论插那里,你都可以共享他
viki117 2010-07-21
  • 打赏
  • 举报
回复
这个共享的结果是,2台电脑都多了一个外设,而2台电脑都不知道其实是同一个COM设备
hyblusea 2010-07-21
  • 打赏
  • 举报
回复
解决方法很多:
1.串口转以太网的设备,比如Nport,将串口数据,以UDP方式广播到到多个客户端

2.采用服务器/客户端, 服务端负责与串口设置交互, 服务端与客户端进行通讯
viki117 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zgke 的回复:]
没用过 一个COM设备被两个人同时访问的.. 你可以考虑做一个SOCKET服务..这个服务来访问COM设备.其他人都访问这个服务..
[/Quote]
本来是可以这样,但是设备是直接共享到2台电脑上去了,如果中间多加一层判断,是解决问题,但是这样一来一回,延时阿,操作起来很不顺畅
viki117 2010-07-21
  • 打赏
  • 举报
回复
COM写数据代码

private bool RedSender(byte[] _code, string portName, int BaudRate, int DataBits, StopBits StopBits)
{
try
{
SerialPort port = new SerialPort(portName);
try
{
port.BaudRate = BaudRate;
port.DataBits = DataBits;
port.StopBits = StopBits;
port.WriteTimeout = 1500;
port.DiscardNull = true;

try
{
if (!port.IsOpen)
port.Open();
port.Write(_code, 0, _code.Length);
port.Close();
port.Dispose();
return true;
}
catch (Exception ex)
{
WriteLog.WLogIn(ex.ToString());
if (port.IsOpen)
{
port.Close();
port.Dispose();
}
return false;
}
}
catch (Exception ex)
{
if (port.IsOpen)
{
port.Close();
port.Dispose();
}
WriteLog.WLogIn(ex.ToString());
return false;
}
}
catch (Exception ex)
{
WriteLog.WLogIn(ex.ToString());
return false;
}
}


未了防止卡死,用了多线程,2.5秒未获得结果,强制关闭线程

private bool WaitResult(Thread thread, ParamTran param)
{
bool result = false;

try
{
//开启循环
DateTime TimeStart = DateTime.Now;
DateTime TimeNow = DateTime.Now;
bool TimeOut = false;
while (!TimeOut)
{
lock (paramObject)
{
if (param.result.ToLower() == "true")
{
result = true;
break;
}
if (param.result.ToLower() == "false")
{
result = false;
break;
}
}
TimeNow = DateTime.Now;
TimeSpan ts = TimeNow - TimeStart;
if (ts.TotalMilliseconds > 2500)
{
TimeOut = true;
}
Thread.Sleep(50);
}
}
catch(Exception ex)
{
WriteLog.WLogIn(ex.ToString());
}

//强制结束线程
try
{
if (thread.ThreadState != ThreadState.Aborted)
thread.Abort();
}
catch
{
}

//跳出循环后返回结果
return result;
}
捷哥1999 2010-07-21
  • 打赏
  • 举报
回复
1、在打开前判断是否断开被占用。try ...catch捕获异常。
2、占用的程序,使用完毕后,释放端口。
加载更多回复(2)

110,534

社区成员

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

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

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