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

本文关键字:线程 文件 服务器 何同步 同步 套接字 | 更新日期: 2023-09-27 18:29:19

我正在编写一个套接字服务器,它接收许多客户端对文件的写入请求。我有一个数组列表来存储套接字侦听器。在我运行客户端发送多达25个请求之后,套接字服务器存储了25个套接字侦听器,并启动了25个线程来接收数据和写入文件。运行后,我从服务器上得到错误,它试图访问被另一个进程锁定的同一个文件。我还得到空引用错误。那么,同步线程以处理所有请求并将所有数据写入文件的最佳方式是什么呢。

感谢您的帮助。谢谢-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);
    }
}

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

在这种情况下,最好序列化对文件的访问,并通过同步队列将所有写请求转发到一个单独的线程,主要原因有两个:

  1. 从多个线程写入/读取机械磁盘上的单个文件不会带来任何性能优势(如果有多个线程,您甚至会看到性能下降)
  2. 您将避免许多同步问题,特别是如果您使用一个预定义的同步队列(如ConcurrentQueue)

这是一个经典的生产者-消费者问题,您可以通过实现管道模式轻松解决它。

基本上,所有线程都会写入同一个线程安全队列,而不是文件。您还需要一个线程,它将从共享集合中逐个读取所有可用的请求并写入文件。

使用.NET 4.X,使用线程安全集合的BlockingCollection类很容易实现。

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

请求处理逻辑(在多个线程中运行)基本上只是将请求添加到队列中:

requestsQueue.Add(request);

将请求转储到文件的线程/任务应该以以下方式使用可用请求:

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