【问题标题】:Best way to add delay to each message received?为收到的每条消息添加延迟的最佳方法?
【发布时间】:2018-07-29 15:13:39
【问题描述】:

我有一个客户端-服务器架构,我每 70 毫秒从客户端向服务器发送一次消息。在服务器端,我想介绍一个模拟的网络延迟。为此,我有以下内容:

//Receive incoming messages and put into temp queue.
private void DataReceived(object sender, DataReceivedEventArgs args)
{
    TemporaryRawMessages.Enqueue(args.Bytes);
    args.Recycle();
}

//Runs on separate thread
void ProcessMessages()
{
    while (true)
    {

        if (TemporaryRawMessages.Count > 0)
        {
            var raw = TemporaryRawMessages.Dequeue();
            Task taskA = Task.Factory.StartNew(() => DelayedReceive(raw));
        }

    }
}

//Process the received message
void DelayedReceive(byte[] raw_message)
{
    //wait a bit before deserialising and queueing the message
    while (sw.ElapsedMilliseconds < LatencyUp) { }
    var message = (ClientToServerMessage)Utils.Deserialize(raw_message);
    Messages_In.Enqueue(message);

}

服务器收到一条消息并将其放入临时队列。 接下来,ProcessMessages() 接收任何新消息并生成一个新任务。该任务在将消息放入另一个队列之前稍等片刻,由主程序拾取。

问题是,如果我对 DelayedReceive 计时,我会看到诸如:3、241、46、99 之类的计时......没有一致性。每条消息都应该延迟 70ms,由网络延迟向上抵消。换句话说,所有消息都会延迟 X(例如 100 毫秒),但在 70 毫秒处等间隔。

对问题所在有什么想法吗?

【问题讨论】:

  • 为什么不能只使用 Thread.Sleep?
  • 如果你的工作是同步的,那么Thread.Sleep(70),如果你的工作是异步的,那么await Task.Delay(70)。现在,您正在使用Task.Factory.StartNew 进行射击并忘记。如果这是用于测试,那么我会删除它并简单地使用Thread.Sleep(70)

标签: c# tcp latency


【解决方案1】:

当创建一个新的Task 时,不能保证它会立即启动,它只是保证代码将在某个时间点执行。

意思是,您的DelayedReceive 方法将在某个时间点被调用。但不一定要马上。

当您在 DelayedReceive 方法中引用外部变量(sw 和 LatencyUp)时,可以解释计时。多个任务可能会以可能错误的顺序引用这些值。

另见:

【讨论】:

  • 有道理。感谢您的澄清。我原以为任务会立即开始。
  • 但是如果你等待Task.Run,那么它会立即与ThreadPool.QueueUserWorkItem一起安排,所以差异可能在~10ms左右
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-01
  • 1970-01-01
相关资源
最近更新 更多