Task.Delay会导致线程切换吗?

问题描述 投票:2回答:1

我有一个运行很长时间的过程,它将数据发送到另一台计算机。但是,这些数据是按块接收的(例如一组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。

c# asynchronous async-await task-parallel-library manualresetevent
1个回答
5
投票

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

不包含您所拥有的代码,因为该代码有错误。它实际上根本不会在周期之间延迟。它创建了一个任务,该任务将在一秒钟内完成,但随后将忽略该任务。您的代码为:

await Task.Delay(1000);

或可能:

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

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

当您以Task.Run开头此代码时,将没有同步上下文-但值得注意的是,同一段代码以不同的方式运行时可能会表现不同。

作为旁注,不清楚向thePacketQueue中添加项目的原因,但是除非是并发集合(例如ConcurrentQueue),否则那里也很可能有问题。

© www.soinside.com 2019 - 2024. All rights reserved.