【发布时间】:2016-10-17 00:11:05
【问题描述】:
这可能是一个基本问题,但我想知道我的编程是否被认为是一种好的做法:-)
我的代码由一个使用底层 tcp 套接字对象的 c# 通信类组成。但它也可以是任何其他支持打开、关闭、读写访问的对象。
单个通信包括发送电报并等待对方的答复。
到目前为止,我只在一个线程中访问了这个 c# 类,并且它运行良好。今天我用几个并行工作线程对其进行了测试,这些线程是在一个表单类中创建并从一个表单类开始的,通信对象是表单类中的一个对象。线程(只是表单类的一个方法)可以随时访问通信对象。
但不幸的是,由于没有锁定,一个线程可以收到另一个线程的应答电报。 为了解决这个问题,我简单地将所有调用函数放在一个 lock(){} 语句中:
public Boolean Read(UInt16 adress,out UInt16 value)
{
lock(this)
{
// send the read telegram and receive
// an ACK Telegram with the data
value = _connection.Read(adress);
}
}
public Boolean Write(UInt16 adress,UInt16 value)
{
lock(this)
{
// send the Write telegram and receive
// an ACK Telegram with the data
return _connection.Write(adress,value);
}
}
此示例中的代码与实际代码不同,但 lock() 是有趣的东西。 我现在的问题是:
- 锁定机制是否足够强大?
- 如果有很多线程在等待进入锁,是否保证每个等待的线程都会获得访问权限?在这种情况下,更快的线程不会阻塞更慢的线程?
- 是否可以编写某种调度程序,让线程一个接一个地访问对象?
[编辑作为评论 #1 的答案]
我无法提供更详细的源代码,因为发布协议细节、套接字封装和所有这些内容的多个对象非常复杂。
- 我的方法都使用对套接字的同步调用。
- 每个方法都会发送一条数据(电报)并等待,直到它得到完整的应答电报或套接字超时。
你写了一些关于排队的文章。我从来没有考虑到这一点。但是 IIRC 我的库的原始实现(2000 年以前的好旧 c++ 代码)需要某种排队来解决 COM/DCOM 通信的这个问题。
也许我应该再看看这段代码。 我在类对象上进行多线程通信的另一个解决方案是同时使用多个类对象。然后每个线程将使用自己的套接字连接,不会有任何混淆。
另一方面,我在通信另一端的目标服务器使用多线程方法来处理每个套接字连接,然后通过一些锁定机制(互斥锁)和同步(事件)将并行电报排队到串行队列中服务器。
[编辑 #2]
当第一个线程调用 Write() 时,不同方法中的 lock(this) 会阻止另一个线程调用 Read() 吗?
【问题讨论】:
-
您研究过排队技术吗?
-
和@CamBruce 说的一样。您永远不会从套接字(或其他)读取/写入多线程。线程如何知道消息何时到达?并且在发送时,您不想在从不同线程发送消息时混淆消息。线程安全不能通过将所有内容都放在锁中来完全修复。如果您提供更多关于您正在实施的内容和方式的信息。我们可能会为您提供替代方案(如果需要)
-
@Elydasian,感谢您编辑我的帖子。看来你手头有很多时间......这个帖子现在有2年了,所以我从来没有怀疑它会再次改变......