2016-06-15 25 views
0

它可能是一个有点基本的问题,但我想知道如果我的节目被接受为良好实践:-)访问来自不同线程单一的ressource(这里是TCP套接字)

我的代码由交流#通信类,它使用底层的TCP套接字对象。但它也可以是支持开放,关闭,读取和写入访问的任何其他对象。

单件通信的包括一个发送一个报文,并等待来自对方的回答。

到现在为止我只从一个线程内访问这个C#类。它工作得很好。今天我用几个并行工作线程对它进行测试,创建并从一个表单类开始,并且通信对象是表单类中的一个对象。线程(只是表单类的一个方法)可以随时访问通信对象。

但不幸的是,因为没有锁定,一个线程可以得到另一个线程的答案电报。 为了解决这个问题,我只是把我所有的调用函数的锁内(){}声明:

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); 
    } 
} 

在此示例代码犯规类似于实际的代码,但锁()是有趣的事情。 我现在的问题是:

  • 是否足够强大的锁定机制?
  • 如果有许多线程正在等待进入锁,是否保证每个等待线程都能访问?在这种情况下,更快的线程不会阻塞较慢的线程?
  • 编程某种类型的调度程序是否可行?它允许线程一个接一个地访问该对象吗?

[编辑为答案评论#1]
我无法提供更详细的源代码,因为它的所有复杂的后 - 多个对象的协议细节,插座封装和所有这些事情。

  • 我的方法都使用对套接字的同步调用。
  • 每方法发送一个数据片(电报),并等待,直到它得到了完整的答案电报或插座超时。

你写一些关于排队。我从来没有把这一因素考虑在内。但是IIRC是我的库的原始实现(来自2000年以前的好的旧C++代码)采用某种排队方式来解决COM/DCOM通信中的这个问题。

也许我应该再看看这个代码一次。 我对我的类对象进行多线程通信的其他解决方案是同时使用多个类对象。然后每个线程将使用它自己的套接字连接,并且不会混淆任何东西。另一方面,我的通信另一端的目标服务器使用多线程方法处理每个套接字连接,然后使用一些锁定机制(Mutexes)和同步(Events)将并行报文排入串行服务器队列。

[编辑#2]
是否在不同的方法锁(本)阻止其他线程调用阅读(),而第一个线程调用write()?

+1

你看过排队技术吗? –

+0

同@CamBruce说。你永远不会从套接字(或其他)读取/写入多线程。线程如何知道消息何时到达他?发送邮件时,您不希望在发送来自不同线程的邮件时混淆邮件。 Threadsafety不能通过将所有内部锁定完全解决。如果您提供了更多关于,您正在实施的内容和方式。我们可能会给你一个替代(如果需要) –

回答

0

我通过我的代码不同的测试去了,好像没有什么不好有关使用

lock(this) 
{} 

但它真的不是很好的做法,读/写从多个线程的插座。 所以我认为我将有两个锁到位:

  • 锁(这个){}
  • 检查Thread.CurrentThread.ManagedThreadId反对在构造函数中使用的。

第一个会阻止同一个线程同时输入两个不同的方法(一个在普通程序流程中,另一个在与invoke-patterns一起使用时)。

相关问题