任务延迟会导致线程切换吗



我有一个长时间运行的进程,它将数据发送到另一台机器。但这些数据是分块接收的(比如一组100个数据包,然后延迟至少10秒(。

我在一个单独的线程上使用Task.Run(() => { SendPackets(); });

要发送的数据包通过一些其他功能在Queue<Packet>对象中排队。

SendPackets()中,我使用while循环来检索和发送(异步(队列中所有可用的项。

void SendPackets()
{
    while(isRunning)
    {
       while(thePacketQueue.Count > 0)
       {
          Packet pkt = thePacketQueue.Dequeue();
          BeginSend(pkt, callback);   // Actual code to send data over asynchronously
       }
       Task.Delay(1000);  // <---- My question lies here
    }
 }

所有的锁都到位了!

我的问题是,当我使用Task.Delay时,下一个周期是否可能由不同于当前周期的线程执行?

有没有其他方法,不用指定1秒的延迟,我可以使用类似ManualResetEvent的东西,以及相应的代码是什么(我不知道如何使用ManualResetEvent

此外,我是async/await和TPL的新手,所以请耐心忍受我的无知。

TIA。

我的问题是,当我使用Task.Delay时,下一个周期是否可能由不同于当前周期的线程执行?

不使用您现有的代码,因为该代码有缺陷。它实际上根本不会在周期之间延迟。它创建一个将在一秒钟内完成的任务,但随后忽略该任务。您的代码应该为:

await Task.Delay(1000);

或潜在:

await Task.Delay(1000).ConfigureAwait(false);

对于第二段代码,它可以在不同的线程上运行每个循环。对于第一段代码,它将取决于同步上下文。如果您在具有线程亲和性的同步上下文中运行(例如,您从WPF或WinForms应用程序的UI线程调用该线程(,那么在延迟完成后,异步方法将在同一线程上继续。如果您在没有同步上下文的情况下运行,或者在不只是使用一个线程的同步上下文中运行,那么它可以在不同的线程中运行每个周期。

当您使用Task.Run启动此代码时,您将不会有同步上下文,但值得注意的是,同一段代码在以不同方式运行时可能会有不同的行为。

顺便说一句,目前尚不清楚是什么在向thePacketQueue添加项目,但除非是并发集合(例如ConcurrentQueue(,否则您很可能也会遇到问题。

最新更新