Task.ContinueWith不调用第二个任务(只有第一个正在运行)
本文关键字:第一个 运行 ContinueWith 调用 第二个 任务 Task | 更新日期: 2023-09-27 18:29:55
我的应用程序允许用户从UI创建"Task"对象并设置它们的执行顺序。从那里,当用户单击"运行"时,所有任务(按顺序)都会被发送到一个类,该类假设要链接并运行它们。类别如下:
public class MaintenanceTask
{
private CancellationTokenSource m_CancellationTokenSource;
private Task m_BatchTask;
public MaintenanceTask()
{
m_CancellationTokenSource = new CancellationTokenSource();
}
public void AddTaskIdent(TaskIdentBase ident)
{
Task newTask = ident.Create(m_CancellationTokenSource.Token);
if (m_BatchTask == null)
m_BatchTask = newTask;
else
m_BatchTask.ContinueWith(prev=>newTask);
}
public void Run()
{
if (m_BatchTask != null)
m_BatchTask.Start();
}
}
AddTaskIdent接收一个基类,该基类知道如何创建Task对象。我的问题是调用Run()会启动发送给类的第一个任务。它运行它,直到它完成之后没有其他任务可以运行。它只是在第一个任务完成后停止。
我是不是错过了ContinueWith机制?
问题出在这一行:
m_BatchTask.ContinueWith(prev=>newTask);
我认为newTask
在从ident.Create
返回时没有启动。所以你应该:
if (m_BatchTask != null)
{
m_BatchTask = newTask;
//you'd like to have the m_lastTask field because next chaining operation
//should be on the last task, not the one you are starting
m_lastTask = newTask;
}
else
{
m_lastTask.ContinueWith(
prev =>
{
newTask.Start();
//doesn't matter to return newTask because in that case
//on second chaining already you will get Task<Task>
return (object)null;
});
m_lastTask = newTask;
}
在合并所有答案的数据并继续谷歌搜索后,它终于开始工作了。工人阶级是:
public class MaintenanceTask
{
private CancellationTokenSource m_CancellationTokenSource;
private Task m_FirstTask;
private Task m_LastTask;
public MaintenanceTask()
{
m_CancellationTokenSource = new CancellationTokenSource();
}
public void AddTaskIdent(TaskIdentBase ident)
{
Task newTask = ident.Create(m_CancellationTokenSource.Token);
if (m_FirstTask == null)
{
m_FirstTask = newTask;
m_LastTask = m_FirstTask;
}
else
{
m_LastTask.ContinueWith(prev => newTask.Start());
m_LastTask = newTask;
}
}
public void Run()
{
if (m_FirstTask != null)
m_FirstTask.Start();
}
}
在调试器中尝试一下,这可能会帮助你了解它的工作原理:
static void Main(string[] args)
{
Task task1 = new Task(() => Console.WriteLine("1"));
Task task2 = new Task(() => Console.WriteLine("2"));
Task task3 = new Task(() => Console.WriteLine("3"));
task1.ContinueWith(previous => task2.Start());
task2.ContinueWith(previous => task3.Start());
task1.Start();
task2.Wait();
Console.WriteLine("Done.");
}
你检查过其他分支是否有吗
else
m_BatchTask.ContinueWith(prev=>newTask);
被称为?
正如我所看到的,当m_Batch任务应用下一个任务时,它最初为空,但没有用引发continue
老实说,我认为您使用Task
不正确。在大多数情况下,Task
表示已经发生的工作。
这就是我在假设C#5的情况下编写您"想要"的代码的方式。
public void AddToQueue(Action action)
{
if (m_BatchTask == null)
m_BatchTask = Task.Run(action);
else
m_BatchTask = AddToQueue(m_BatchTask, action);
}
public async Task AddToQueue(Task existingTask, Action action)
{
await existingTask;
action();
}