Task.Delay能引起线程切换吗?
Can Task.Delay cause thread switching?
我有一个很长的 运行 进程将数据发送到另一台机器。但是这个数据是以块的形式接收的(比如一组 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。
My question is, when I use Task.Delay, is it possible then the next cycle may be executed by a thread different from the current one?
不适用于您的代码,因为该代码存在错误。它实际上根本不会在周期之间延迟。它创建了一个将在一秒钟内完成的任务,但随后忽略了该任务。您的代码 应该 是:
await Task.Delay(1000);
或可能:
await Task.Delay(1000).ConfigureAwait(false);
使用第二段代码,可以绝对 运行每个循环在不同的线程上。对于第一段代码,它将取决于同步上下文。如果您 运行 处于具有线程亲和性的同步上下文中(例如,您从 WPF 或 WinForms 应用程序的 UI 线程调用它),那么异步方法将在同一线程上继续延迟完成。如果您 运行 在没有同步上下文的情况下,或者在不只使用一个线程的同步上下文中,那么它又可以 运行 每个周期在不同的线程中。
当您使用 Task.Run
开始此代码时,您将没有同步上下文 - 但值得注意的是,当 运行 在不同的方式。
附带说明一下,不清楚是什么向 thePacketQueue
添加项目,但除非那是并发集合(例如 ConcurrentQueue
),否则您也可能遇到问题。
我有一个很长的 运行 进程将数据发送到另一台机器。但是这个数据是以块的形式接收的(比如一组 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。
My question is, when I use Task.Delay, is it possible then the next cycle may be executed by a thread different from the current one?
不适用于您的代码,因为该代码存在错误。它实际上根本不会在周期之间延迟。它创建了一个将在一秒钟内完成的任务,但随后忽略了该任务。您的代码 应该 是:
await Task.Delay(1000);
或可能:
await Task.Delay(1000).ConfigureAwait(false);
使用第二段代码,可以绝对 运行每个循环在不同的线程上。对于第一段代码,它将取决于同步上下文。如果您 运行 处于具有线程亲和性的同步上下文中(例如,您从 WPF 或 WinForms 应用程序的 UI 线程调用它),那么异步方法将在同一线程上继续延迟完成。如果您 运行 在没有同步上下文的情况下,或者在不只使用一个线程的同步上下文中,那么它又可以 运行 每个周期在不同的线程中。
当您使用 Task.Run
开始此代码时,您将没有同步上下文 - 但值得注意的是,当 运行 在不同的方式。
附带说明一下,不清楚是什么向 thePacketQueue
添加项目,但除非那是并发集合(例如 ConcurrentQueue
),否则您也可能遇到问题。