简体   繁体   English

如何同步套接字服务器中的线程以写入文件

[英]How to synchronize threads in socket server for writing to file

I am writing a socket server which receives many client request to write to a file. 我正在写一个套接字服务器,它接收许多客户端请求写入文件。 I have an arraylist to store the socketlisteners. 我有一个arraylist来存储socketlisteners。 After I ran the client to send up to 25 requests, which results in the socket server storing 25 socketlisteners and starting 25 threads to receive the data and write to the file. 在我运行客户端以发送最多25个请求之后,套接字服务器存储了25个套接字侦听器,并启动了25个线程来接收数据并写入文件。 After running I get errors from the server that its trying to access the same file which is locked by another process. 运行后,我从服务器收到错误消息,它试图访问被另一个进程锁定的同一文件。 I also get null reference errors. 我也得到空引用错误。 So, what is the best way to synchronize the threads so all the requests get processed and all the data get written to the file. 因此,同步线程以使所有请求得到处理并将所有数据写入文件的最佳方法是什么。

Any help is appreciated. 任何帮助表示赞赏。 Thanks. 谢谢。 -CR -CR

string data = Encoding.ASCII.GetString(byteBuffer,0, size);

if (!File.Exists(filepath))
{
    using (StreamWriter sw = File.CreateText(filepath))
    {
        sw.WriteLine(data);  
    }
}
else
{
    using (StreamWriter sw = File.AppendText(filepath))
    {
        sw.WriteLine(data);
    }
}

This is a classical Producer Consumer problem , you can easily solve it by implementing Pipeline pattern. 这是一个经典的Producer Consumer问题 ,您可以通过实现Pipeline模式轻松解决。

Basically all threads would write into the same thread-safe queue rather than file. 基本上所有线程都将写入同一线程安全队列,而不是文件。 And you need one more thread which will read from the shared collection all available requests one by one and write to a file. 并且您还需要一个线程,该线程将从共享集合中读取所有可用请求,并将其写入文件。

Using .NET 4.X it is easy to implement using BlockingCollection class which is thread-safe collection. 使用.NET 4.X,可以很容易地使用BlockingCollection类(该类是线程安全的集合)来实现的。

// request queue represented by a single string
var requestsQueue = new BlockingCollection<string>(); 

Request processing logic (which run in multiple threads) basically just add requests into the queue: 请求处理逻辑(在多个线程中运行)基本上只是将请求添加到队列中:

requestsQueue.Add(request);

Thread/Task which dumps requests to a file should consume available requests in following way: 将请求转储到文件的线程/任务应通过以下方式消耗可用请求:

using (StreamWriter sw = File.CreateText(filepath))     
{         
    foreach (var request in requestsQueue.GetConsumingEnumerable())
    {
       sw.WriteLinerequest);
    }
}

In such situations it's better to serialize access to the file and forward all write requests to a separate thread via a synchronized queue for two main reasons: 在这种情况下,最好将对文件的访问序列化,并通过同步队列将所有写请求转发到单独的线程,这有两个主要原因:

  1. Writing/reading to a single file on a mechanical disk from multiple threads will not yield any performance benefit (if there are many threads you will even see performance degradation). 从多个线程向机械磁盘上​​的单个文件进行写入/读取不会产生任何性能上的好处(如果有很多线程,您甚至会发现性能下降)。
  2. You will avoid a lot of synchronization problems, especially if you use one of the predefined synchronized queue like ConcurrentQueue . 您将避免很多同步问题,特别是如果您使用预定义的同步队列之一(例如ConcurrentQueue) ,则尤其如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM