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

Man*_*lal 5 c# asynchronous manualresetevent task-parallel-library async-await

我有一个长时间运行的进程将数据发送到另一台机器。但是这些数据是分块接收的(比如一组 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
    }
 }
Run Code Online (Sandbox Code Playgroud)

所有的锁都到位了!

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

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

另外,我是 async/await 和 TPL 的新手,所以请容忍我的无知。

TIA。

Jon*_*eet 10

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

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

await Task.Delay(1000);
Run Code Online (Sandbox Code Playgroud)

或可能:

await Task.Delay(1000).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

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

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

作为旁注,尚不清楚向 中添加项目的内容thePacketQueue,但除非是并发集合(例如ConcurrentQueue),否则您也可能会遇到问题。

  • 他们已经表明他们正在使用“Task.Run”来开始(他们显示的代码)运行。我认为这意味着没有同步上下文。 (2认同)