2013-12-15 32 views
0

我正在创建一个客户端 - 服务器结构,其中服务器为每个客户端都有一个线程。 该特定线程仅发送和接收数据。在服务器的主线程中,我想读取clientthread收到的输入。但是在mainthread正在阅读的同时,这个输入可能会被clientthread修改。我会如何防止这种情况?我读过锁,但不知道如何以这种方式实现它们。锁定资源或不在多线程服务器

我的问题的第二部分是:clientthread是一个不断从网络流读取的循环,因此阻塞该线程,直到它可以读取某些内容。但是,我可以从我的主线程调用一个函数(该函数会通过该网络流发送一些东西),现有的clientthread(即循环)必须执行?

对不起,我现在不能给任何代码,但我认为这足够清楚了吗?

+1

恐怕这个描述太含糊了。代码会更好。我不明白你会如何得到更多的一般性建议。 – usr

+0

其实它只是一般的建议,我需要:) –

+1

你必须使用锁定来防止事故。如果你有一个不重要的客户端连接数,这将对吞吐量产生非常不利的影响,所有这些线程都会在锁上争夺。你解决这个问题是不要这样做,最好的一般建议。 –

回答

1

听起来像生产者 - 消费者设计可能很适合你的问题。一般而言,客户端线程会将接收到的数据放入(线程安全)队列中,之后不会对其进行修改 - 任何到达的新数据都会进入队列中的新插槽。然后,主线程可以等待任何队列中的新数据并在其到达时进行处理。主线程可以定期检查所有队列,或者(更好)在数据放入队列时接收某种通知,以便在没有任何事情发生时可以休眠,并且不会占用CPU时间。

既然你问锁:这是一个基本的基于锁的实现作为替代队列,也许,这将有助于你明白一个道理

class IncomingClientData 
{ 
    private List<byte> m_incomingData = new List<byte>(); 
    private readonly object m_lock = new object(); 

    public void Append(IEnumerable<byte> data) 
    { 
     lock(m_lock) 
     { 
      m_incomingData.AddRange(data); 
     } 
    } 

    public List<byte> ReadAndClear() 
    { 
     lock(m_lock) 
     { 
      List<byte> result = m_incomingData; 
      m_incomingData = new List<byte>(); 
      return result; 
     } 
    } 
} 

在这个例子中,客户端线程将调用Append与他们收到的数据以及主线程可以通过调用ReadAndClear收集自上次检查以来收到的所有收到的数据。

这是线程安全的通过锁定在这两个函数的所有代码上m_lock,这只是一个普通的简单的对象 - 你可以在C#中的任何物体锁定,但我相信这可能会造成混淆,实际上导致微妙如果不小心使用了错误,所以我几乎总是使用专用对象来锁定。一次只有一个线程可以锁定对象,因此这些函数的代码一次只能在一个线程中运行。例如,如果您的主线程在客户线程仍然忙于将数据追加到列表中时调用ReadAndClear,那么主线程将等待客户线程离开Append函数。

这不是要求为此创建一个新类,但它可以防止意外,因为我们可以小心控制共享状态如何被访问。例如,我们知道在ReadAndClear()中返回内部列表是安全的,因为当时不能有其他参考。

现在为您的第二个问题:只是简单地调用一个方法将永远不会导致该方法在不同的线程上运行,无论该方法在哪个类中。Invoke是WinForms UI线程的一个特殊功能,您如果你想在你的工作线程中使用Invoke,你必须自己实现这个功能。在内部,Invoke的工作方式是将要运行的代码放入应该在UI线程上运行的所有事物的队列中,包括UI事件。 UI线程本身基本上是一个循环,它总是从该队列中提取下一项工作,然后执行该工作,然后从队列中获取下一项,等等。这也是为什么你不应该在事件处理程序中长时间工作 - 只要UI线程忙于运行你的代码,它将无法处理其队列中的下一个项目,所以你会支持所有发生的其他工作项目/事件。

如果你想要你的客户端线程运行某个功能,你必须实际提供代码 - 例如让客户端线程检查某个队列中主线程的命令。

+0

感谢您对我的抽象问题的完整回答!现在我想知道该怎么做,再次感谢。但是对于第二部分,例如,我将无法与委托人一起完成这项工作。 –

+0

你可以使用代表,但有趣的问题是你会*与他们做什么。 – Medo42

+0

我编辑了我的问题的第二部分。这可能吗?我将如何实现这一目标?在此先感谢 –