用于 C# 在进程完成之前完成的基于事件的任务框架

Event based Task framework for C# completing before process complete

我正在尝试创建一个系统来处理作为单独任务传入的事件。这一切都在一个 Windows 服务应用程序中,该应用程序一直运行到停止为止,停止时会等到所有任务完成后再停止。

我有以下简化代码:

IList<Task> _tasks = new List<Task>();//this is a private class variable.

private void Event_Fired(object sender, eventArgs e)
{
    StartTask();
}

private void StartTask(){
    Task task = Task.Factory.StartNew(async () => await process.ProcessEvent(true, StoppingToken));
   _tasks.Add(task);
}

private void MonitorTasks(){
    for (int i = _tasks.Count - 1; i >= 0; i--)
    {
        Task aTask = _laneTasks[i];
        if (aTask.IsCompleted)
        {
            _tasks.Remove(aTask);
            Log.Information($"Task {aTask.Id} completed.");
        }
    }
}

public async Task ProcessEvent(){
    //do some async processing
    await Task.Delay(5000); //if I add a delay before returning the Task, it is completed prior to this delay.
}

我遇到的问题是任务在 ProcessEvent 完成之前 正在完成。我需要确保在允许进程停止之前完成任务。

该进程还必须允许新事件随时进入并产生新任务。

我觉得我在这里缺少一些基本的东西。任何帮助将不胜感激。

这可能是你的问题:

Task task = Task.Factory.StartNew(async () => await process.ProcessEvent(true, StoppingToken));

这会启动一个新任务,该任务会立即完成。请尝试 运行 任务。

Task task = Task.Run(() => process.ProcessEvent(true, StoppingToken));

Task.Factory.StartNew(...) 创建一个新的 Task 来执行提供的委托。 returned Task 的具体类型将取决于委托的 return 类型。

那么让我们看看您传入的委托:

async () => await process.ProcessEvent(true, StoppingToken)

好的,那是 Func<Task>。调用该函数将创建一个新的 Task 和 return 它。所以你的 Task<Task> 立即完成,Result 值设置为内部 Task 对象。

更复杂的是,ProcessEvent() 本身创建了一个 Task,最终就是您要等待的内容。所以你正在创建一个 Task 来创建一个 Task 来等待 Task。当然 outer-most Task 会在服务员 Task 创建后立即完成,因为它的工作现在已经 完成 .

由于您的代码已经在 Task 对象集合中进行手动等待,因此您不需要 Task 其全部目的是等待最里面的 Task 完成.并且由于您已经 return 从 ProcessEvent() 创建 Task,因此您不需要 Task 来创建 Task.

改为这样做:

_tasks.Add(ProcessEvent());