如何解决在一个线程上连续运行任务
我有几个线程(正在做服务器工作),需要将要在主线程上完成的工作排队(它们需要访问只能从主线程调用的API)。
使用Task系统对我来说很有意义,因为服务器线程可以生成使用此仅主线程的API的任务,将它们排队在主线程上运行并等待它们。主线程可以旋转并从ConcurrentQueue中弹出任务,然后在任务进入时运行它们。
从本质上讲,这与通常的模式有所不同,在该模式下,任务跨线程池并行运行。在这里,任务是从其他多个线程创建的,并排队等待在一个主线程上运行。
现在起皱纹:其中一些任务可能会产生子任务,这些子任务本身需要在主线程上运行。例如:
# On server thread:
Task taskA = new Task(async () => {
Task taskB = new Task(() => Console.WriteLine("some sub work"));
MainThreadWorkQueue.BeginInvoke(taskB);
await taskB;
});
MainThreadWorkQueue.BeginInvoke(taskA);
await taskA;
这可能是因为顶层任务之一是使用库代码,而库代码本身需要在主线程上运行。
因此,我最终得到一个类似树的任务结构,其中根级任务需要阻止等待叶任务完成,但是根任务也在执行时动态创建这些叶任务。
问题是我不确定如何编写主线程代码。我在想类似的东西:
// Main thread:
while(true) {
Task currentTask;
while (MainThreadWorkQueue.TryDequeue(out currentTask)) {
currentTask.Wait();
}
// Do other work
}
但是,这将在上面的taskA示例中陷入僵局,因为taskB被排队,但是taskA永远不会完成以允许taskB的工作开始。
理想情况下,我想执行以下操作:
// Main thread:
while(true) {
Task currentTask;
while (MainThreadWorkQueue.TryDequeue(out currentTask)) {
currentTask.RunUntilFinishedOrBlocked();
if (currentTask.IsBlockedOnOtherTask) {
MainThreadWorkQueue.Enqueue(currentTask)
}
}
// Do other work
}
是否有一种方法可以运行任务,直到该任务被其他任务阻止为止?还是解决该问题的另一种方法?
解决方法
You should never use the Task
constructor。它的用例几乎为零。
在您的情况下,您要查找的类型不是Task
;这是一个委托人:
我正在尝试使用任务来代表工作单位
Task
是错误的类型。听起来更像Func<Task>
。
我想先运行taskA,直到它阻塞,然后再运行taskB,然后继续运行taskA。
在这种情况下,应使用单线程的SynchronizationContext
。您可以通过在UI线程上运行这些任务,也可以在AsyncContext
之类的文件中运行它们来完成此任务。 AsyncContext
有一个内置的工作队列,直到完成为止。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。