C#-项集合的延迟执行

C#-项集合的延迟执行,c#,while-loop,thread-sleep,C#,While Loop,Thread Sleep,我收集了10万件物品。项有2个属性。(1) 时间戳和(2)数据。集合中的每个项都有一个时间戳,该时间戳或比以前的项多几个(不同)毫秒。我需要将这些项目发送到TCP端点,以保持它们之间的时间延迟。也就是说,如果第一项和第二项之间的时差是300毫秒,那么在发送第一项之后,我应该等待300毫秒,然后发送第二项 在找到连续项目之间的时间差后,我尝试了Thread.Sleep。对于第一个项目和最后一个项目之间的时差为40秒的列表,使用Thread.Sleep发送所有项目大约需要70-80秒 DateTim

我收集了10万件物品。项有2个属性。(1) 时间戳和(2)数据。集合中的每个项都有一个时间戳,该时间戳或比以前的项多几个(不同)毫秒。我需要将这些项目发送到TCP端点,以保持它们之间的时间延迟。也就是说,如果第一项和第二项之间的时差是300毫秒,那么在发送第一项之后,我应该等待300毫秒,然后发送第二项

在找到连续项目之间的时间差后,我尝试了Thread.Sleep。对于第一个项目和最后一个项目之间的时差为40秒的列表,使用Thread.Sleep发送所有项目大约需要70-80秒

DateTime currenTimeStamp;
DateTime nextTimeStamp;
TimeSpan timeDiff;

using (NetworkStream stream = client.GetStream())
{
    for (int i = 0; i < count; i++)
    {
        //some lines here to do the TCP transfer

        currenTimeStamp = //get current item's time stamp;
        nextTimeStamp = //get next item's time stamp;
        timeDiff = nextTimeStamp - currenTimeStamp;
        Thread.Sleep(timeDiff);
    }
}
DateTime-currenTimeStamp;
日期时间nextTimeStamp;
时间跨度时间差;
使用(NetworkStream=client.GetStream())
{
for(int i=0;i
后来,我通过比较当前发送时间和预期发送时间,尝试在while循环中等待。处理整个项目大约需要50-55秒。同时,CPU在while循环的整个过程中都很忙

DateTime currenTimeStamp;
DateTime nextTimeStamp;
DateTime TimeToSendNextItem;
TimeSpan timeDiff;

using (NetworkStream stream = client.GetStream())
{
    for (int i = 0; i < count; i++)
    {
        //some lines here to do the TCP transfer

        currenTimeStamp = //get current item's time stamp;
        nextTimeStamp = //get next item's time stamp;
        timeDiff = nextTimeStamp - currenTimeStamp;
        TimeToSendNextItem = DateTime.UtcNow.Add(timeDiff);
        while (DateTime.UtcNow < TimeToSendNextItem) { }
    }
}
DateTime-currenTimeStamp;
日期时间nextTimeStamp;
DateTime TimeToSendNextItem;
时间跨度时间差;
使用(NetworkStream=client.GetStream())
{
for(int i=0;i

我怎样才能以最小的延迟有效地处理这个问题?通过最小延迟,我的意思是在第一个和最后一个项目之间的原始40秒时间差内发送这些项目。

请记住,当您使用Thread类时,操作系统可以控制正在执行的进程,您无法控制执行时间,我认为您无法使用Thread类解决此问题。

您可能需要在这里考虑一些行来执行TCP传输
操作时间。(如果它们是同步的。)

我将使用您的第一个代码段作为示例

DateTime currenTimeStamp;
DateTime nextTimeStamp;
TimeSpan timeDiff;

using (NetworkStream stream = client.GetStream())
{
    for (int i = 0; i < count; i++)
    {
        var start = DateTime.Now;
        //some lines here to do the TCP transfer
        var operationDiff = DateTime.Now - start;
        currenTimeStamp = //get current item's time stamp;
        nextTimeStamp = //get next item's time stamp;
        timeDiff = nextTimeStamp - currenTimeStamp - operationDiff;
        Thread.Sleep(timeDiff);
    }
}
DateTime-currenTimeStamp;
日期时间nextTimeStamp;
时间跨度时间差;
使用(NetworkStream=client.GetStream())
{
for(int i=0;i
编辑: 由于您有10万件物品,实际操作时间比预期多10~15分钟。 这是每项0.1毫秒,如果您需要更多帮助,请在此处编辑您的帖子,以便执行TCP传输

同样
Thread.Sleep
精度取决于硬件时钟。如果您需要更精确的定时,您可能需要实时库和特定硬件(用于时钟)


使用while是要求进程“不要停止,继续检查”,这样操作所需的时间就会减少。

使用计时器尝试此代码

        class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Adding elements to list");
            List<WorkItem> workItems = new List<WorkItem>(100);
            for (int i = 0; i < 1000; i++)
            {
                workItems.Add(new WorkItem
                {
                    TimeStamp = DateTime.Now.AddMilliseconds(i * 300)
                });
            }
            var tw = new TimedWorker();
            tw.Process(workItems);

            Console.ReadLine();
        }
    }
    class TimedWorker
    {
        private Timer _timer;
        private Queue<WorkItem> _workItems;
        public void Process(List<WorkItem> workItems)
        {
            _timer = new Timer
            {
                AutoReset = false,
                Interval = 1
            };
            _workItems = new Queue<WorkItem>();
            _timer.Elapsed += Elapsed;
            foreach (var item in workItems)
            {
                _workItems.Enqueue(item);
            }
            _timer.Start();
        }

        private void Elapsed(object sender, ElapsedEventArgs e)
        {
            ProcessNext();
        }

        private void ProcessNext()
        {
            var item = _workItems.Dequeue();
            var nextItem = _workItems.Peek();
            _timer.Interval = (nextItem.TimeStamp - item.TimeStamp).TotalMilliseconds;
            Console.WriteLine(item.TimeStamp.ToString("hh/mm/ss:FFFFFF"));
            _timer.Start();
        }
    }

    class WorkItem
    {
        public DateTime TimeStamp;
    }
类程序
{
静态void Main(字符串[]参数)
{
Console.WriteLine(“向列表中添加元素”);
列表工作项=新列表(100);
对于(int i=0;i<1000;i++)
{
工作项。添加(新工作项
{
TimeStamp=DateTime.Now.add毫秒(i*300)
});
}
var tw=新的TimedWorker();
tw.过程(工作项);
Console.ReadLine();
}
}
类计时工
{
私人定时器;
专用队列工作项;
公共作废流程(列出工作项)
{
_定时器=新定时器
{
自动重置=错误,
间隔=1
};
_workItems=新队列();
_timer.appeated+=已用时间;
foreach(工作项中的变量项)
{
_工作项排队(项);
}
_timer.Start();
}
私有无效已过(对象发送方,ElapsedEventArgs e)
{
ProcessNext();
}
私有void ProcessNext()
{
var item=_workItems.Dequeue();
var nextItem=_workItems.Peek();
_timer.Interval=(nextItem.TimeStamp-item.TimeStamp).total毫秒;
Console.WriteLine(item.TimeStamp.ToString(“hh/mm/ss:FFFFFF”);
_timer.Start();
}
}
类工作项
{
公共日期时间戳;
}

如果您使用的是最新的C#8.0,您可以使用
iSyncEnumerable
为您提供所需的项目:

private async IAsyncEnumerable<Item> GetItemAfterDelay(IEnumerable<Item> items)
{
    DateTime previousItemTimestamp = items.First().Timestamp;

    foreach(var i in items)
    {
        var delay = i.Timestamp - previousItemTimestamp;

        await Task.Delay(delay);

        yield return i;

        previousItemTimestamp = i.Timestamp;
    }
}
此方法将在当前时间戳和前一个时间戳之间的差异之后从数组返回一个项

然后,您可以对返回的项进行迭代,并执行TCP传输

using (NetworkStream stream = client.GetStream())
{
    // assuming your collection is called `myCollection`
    await foreach(var item in GetItemAfterDelay(myCollection))
    {
        //some lines here to do the TCP transfer
    }
}

关键是测量从您发送的第一个项目开始经过的时间,然后确保没有项目提前处理。因为您无法控制的其他因素可能会导致处理延迟。(假设c#8)

专用异步IAsyncEnumerable GetItemAfterDelay(IEnumerable items)
{
var e=items.GetEnumerator();
if(如MoveNext()){
var start=DateTime.Now;
var firstTime=e.Current.Timestamp;
using (NetworkStream stream = client.GetStream())
{
    // assuming your collection is called `myCollection`
    await foreach(var item in GetItemAfterDelay(myCollection))
    {
        //some lines here to do the TCP transfer
    }
}