确保按正确顺序发送排队的邮件

时间:2018-02-20 10:20:41

标签: c# multithreading tcp

我有一个客户端 - 服务器架构,使用TCP进行通信。客户端以1msg / 70ms的速率向客户端发送消息。服务器必须模拟网络延迟,因此在服务器接收方面,我会执行以下操作:

A

注意//Event handler for new messages private void DataReceived(object sender, DataReceivedEventArgs args) { //Add raw data to a queue for processing at a later time TemporaryRawMessages.Enqueue(args.Bytes); args.Recycle(); } //Function running on thread; processes newly arrived raw messages //new messages are removed from the queue, given their own thread and processed independently. void ProcessMessagesIn() { while (true) { if (TemporaryRawMessages.Count > 0) { var raw = TemporaryRawMessages.Dequeue(); var t = new Thread(() => { Thread.Sleep(LatencyUp); var message = (ClientToServerMessage)Utils.Deserialize(raw_message); Messages_In.Enqueue(message); }); t.Start(); } } } //Create & start a thread to processes incoming messages var processMessagesIn = new Thread(ProcessMessagesIn); processMessagesIn.Start(); 变量。我希望来自客户端的消息延迟b x毫秒,但均匀间隔为1msg / 70ms。换句话说,所有消息相隔70毫秒,但偏移LatencyUp

我还将消息从服​​务器发送到客户端,以表示网络停机延迟:

LatencyUp

我也试过像这样发送,没有从服务器到客户端的消息队列:

Task.Factory.StartNew(() => { SendLoop(); });

void SendToClient(ServerToClientMessage message)
{
    Messages_Out.Enqueue(message);
}

void SendLoop()
{
    while (true)
    {
        if(Messages_Out.Count > 0)
        {
            ServerToClientMessage message_out = null;
            Messages_Out.TryDequeue(out message_out);

            if(message_out != null)
            {
                Thread myNewThread = new Thread(() =>
                {
                    Thread.Sleep(LatencyDown);
                    if (ClientConnection != null && ClientConnection.State == ConnectionState.Connected)
                    {
                        var serialized = Utils.Serialize(message);
                        ClientConnection.SendBytes(serialized, SendOption.Reliable);
                    }
                });

                myNewThread.Start();
            }
        }
    }
}

问题

有时从服务器到客户端的消息混淆了......例如,消息2可能会在消息1之前发送。

我不完全确定原因。消息以正确的顺序放入队列(我已经检查了这个)。在添加到队列和出队+发送之间的某处,出现了问题。

我唯一能想到的是一个线程在另一个线程之前完成,但我无法想象这会如何发生。

我可以做些什么来确保按照发送的顺序(客户端到服务器)接收邮件,并以正确的顺序从服务器发送到客户端?

性能(在处理速度方面)非常重要,因此有关该主题的任何改进/建议也将受到赞赏。

1 个答案:

答案 0 :(得分:0)

您不能使用多个线程按顺序分派事件。如果您想为数据生成器创建异步使用者,那么您只需要一个线程。

创建生产者 - 消费者队列的最简单方法是使用BlockingCollection<T>

var blockingCollection = new BlockingCollection<int>();

// this is a single, one and only producer thread
Task.Run(() =>
{
    var number = 0;
    while (true)
    {
        number++;
        Console.WriteLine("tx --> " + number);
        blockingCollection.Add(number);
        Task.Delay(1000).Wait();
    }
});

// single, one and only consumer thread
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
    Task.Delay(200).Wait();
    Console.WriteLine("    " + item + " --> rx");
}