c# - Task.Delay 会导致线程切换吗?
问题描述
我有一个长时间运行的进程将数据发送到另一台机器。但是这些数据是以块的形式接收的(比如一组 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
),否则您很可能也有问题。
推荐阅读
- rabbitmq - 将 Node-RED 连接到 RabbitMQ 优先级队列?
- ruby-on-rails - Rails SSE 不适用于 Unicorn 服务器
- angular -
不是离子 4 中的已知元素 - android - 任务 ':app:processDebugResources' 执行失败。> Android 资源链接失败
- laravel - 此请求目前无法通过 localhost 处理错误
- python - 使用 python-3 在 HTML 字符串中搜索类名
- google-bigquery - Big-Query 中非空值的“错误双值”错误
- mysql - 从表中执行查询并根据结果执行另一个查询?
- nginx - 通过 Nginx 更改代理的响应头
- exception-handling - 处理无效的文件句柄(可能还有其他无效对象)