【发布时间】:2020-12-03 07:41:30
【问题描述】:
我有几个线程(做服务器工作)需要排队在主线程上完成工作(他们需要访问只能从主线程调用的 API)。
使用任务系统对我来说很有意义,因为服务器线程可以生成使用这个仅主线程 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
}
有没有办法运行一个任务,直到它被另一个任务阻塞?或者用不同的方法来解决这个问题?
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
标签: c# async-await task task-parallel-library