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机制?

Task.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();
    }
}
请注意,"foo.ContinuteWith(completedTask=>otherTask);"不会启动otherTask。您需要类似于"foo.ContineWith(completedTask=>otherTask.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();                       
}