gpt4 book ai didi

c# - 对我的应用程序中的线程安全性有何建议?

转载 作者:行者123 更新时间:2023-12-03 13:22:03 24 4
gpt4 key购买 nike

我的TcpServer中有以下方法

    private void Receive(ZClient client)
{
NetworkStream ns = client.TcpClient.GetStream();
int bytesRead = 0;
byte[] message = new byte[client.TcpClient.ReceiveBufferSize];
while (true)
{
bytesRead = ns.Read(message, 0, client.TcpClient.ReceiveBufferSize);
if (bytesRead == 0)
{
break; // Exit Thread
}
else
{
Array.Resize<Byte>(ref client.Buffer, client.Buffer.Length + bytesRead);
Buffer.BlockCopy(message, 0, client.Buffer, client.Buffer.Length - bytesRead, bytesRead);
// Issue Below
DisassembleRawMessage(client); // *1 See below
new Thread(()=>DeQueueMessages(client)).Start(); // *2 See below
// End Issue
}
}
}
  • DissassembleRawMessage负责处理缓冲区的处理,并将单个消息放入客户端消息队列中。没问题
  • DeQueueMessages负责处理先前放置在DissassembleRawMessage方法中我的客户端消息队列中的对象。

  • 这个问题似乎很明显。收到消息后,我分出了一个新线程。在对单个消息进行去队列和处理的过程中,队列中可能添加了更多项目,因为在此期间可能已接收到更多数据。这导致枚举错误,提示我在枚举过程中不得修改集合的内容。

    我不想通过在同一线程内处理队列来阻塞我的receve方法,因为它会破坏允许队列建立请求同时仍接收数据的目的。如何继续对对象进行排队,同时处理队列中的对象而又不会遇到枚举修改异常?

    更新:使消息出队的方法。
    while (client.Queue.Count() > 0)
    {
    byte[] buffer = client.Queue.Dequeue();
    ...
    }

    最佳答案

    首先,我不会为收到的每条消息使用新线程。启动一个等待新工作而不是退出的线程,或者使用ThreadPool。

    如果在枚举过程中收到InvalidOperationException,则意味着您正在遍历列表或其他IEnumerable。这是否意味着您正在做类似的事情?

    void DeQueueMessages(ZClient client)
    {
    foreach(Message m in client.messageList)
    {
    ...
    }
    messageList.Clear();
    }

    如果是这样,请切换为使用实际的Queue类,并在while循环中执行以下操作:
    void DeQueueMessages(ZClient client)
    {
    while(client.messageQueue.Count > 0)
    {
    Message m = client.messageQueue.Dequeue();
    ...
    }
    }

    如果有内存,则标准的System.Collections.Generic.Queue类不是线程安全的,因此我将使用System.Collections.Concurrent.ConcurrentQueue。

    关于c# - 对我的应用程序中的线程安全性有何建议?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4169404/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com