重复使用并发运行的任务

本文关键字:运行 任务 并发 | 更新日期: 2023-09-27 17:58:33

好的,我已经改变了问题本身,因为我认为它不是很清楚。

public void Start()
{
    IEnumerable<Action> originalTasks = new Action[] { () => LongRunningMethod(), () => LongRunningMethod2() };
    Parallel.ForEach(originalTasks, task =>
    {
        task.Invoke();
    });
}
public void LongRunningMethod()
{
    Console.WriteLine("Long running method executed.");
    Thread.Sleep(10000);
}
public void LongRunningMethod2()
{
    Console.WriteLine("Long running method 2 executed.");
}

您将看到我有两个方法"LongRunningMethod()"answers"LongRunning Method2()"。"LongRunningMethod"的睡眠时间为10秒。

以下是我想要实现的目标。

应该输入并行foreach(事实就是这样),一旦我进入并行循环,5秒的计时器就会启动。当这5秒钟结束时,我想重新运行并行循环(我知道在这种情况下这不好,因为我正在启动一个线程,而另一个线程仍在运行。

在生产环境中,每个任务都有一个名为"isRunning"的变量,我将使用它来查看是否可以重新运行它。

我希望有人能在这个问题上给我一些帮助。

亲切问候,

重复使用并发运行的任务

也许您可以使用自定义状态对象来控制程序的流程。该状态对象将在延续方法中使用,以确定哪些任务已完成并应重新安排。

样品:

class TaskState
{
    public int OneSecondTaskId { get; set; }
    public int TenSecondTaskId { get; set; }
    public bool ShouldRescheduleOneSecondTask { get; set; }
    public bool ShouldRescheduleTenSecondsTask { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Task oneSecondTask = null;
        Task tenSecondTask = null;
        var state = new TaskState()
                        {
                            ShouldRescheduleOneSecondTask = true,
                            ShouldRescheduleTenSecondsTask = true
                        };
        while (true)
        {
            if (state.ShouldRescheduleOneSecondTask)
            {
                oneSecondTask = Task.Factory.StartNew(
                    () =>
                    {
                        Thread.Sleep(1000);
                        Console.WriteLine("Slept 1 second");
                    });
                state.OneSecondTaskId = oneSecondTask.Id;
                state.ShouldRescheduleOneSecondTask = false;
            }
            if (state.ShouldRescheduleTenSecondsTask)
            {
                tenSecondTask = Task.Factory.StartNew(
                    () =>
                    {
                        Thread.Sleep(10000);
                        Console.WriteLine("Slept 10 seconds");
                    });
                state.TenSecondTaskId = tenSecondTask.Id;
                state.ShouldRescheduleTenSecondsTask = false;
            }
            var handleTaskCompletionTask = Task.WhenAny(oneSecondTask, tenSecondTask).ContinueWith(
                (completedTask, o) =>
                {
                    var taskState = (TaskState)o;
                    var taskId = completedTask.Result.Id;
                    if (taskId == taskState.OneSecondTaskId)
                    {
                        taskState.ShouldRescheduleOneSecondTask = true;
                    }
                    if (taskId == taskState.TenSecondTaskId)
                    {
                        taskState.ShouldRescheduleTenSecondsTask = true;
                    }
                }, state);
            handleTaskCompletionTask.Wait();
        }
    }
}

输出:

Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 10 seconds
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 1 second
Slept 10 seconds
Slept 1 second
Slept 1 second
...

因此,首先,为了在每个任务结束后运行一些代码,并对该任务进行进一步处理,您需要对每个任务调用ContinueWith

要在它们全部启动5分钟后做某事,您可以使用Task.Delay

IEnumerable<Task> originalTasks = CreateTasks();
var continuations = originalTasks.Select(task => 
    task.ContinueWith(t =>
    {
        DoStuffWithTask(t);
    }))
    .ToList();
Task.Delay(TimeSpan.FromMinutes(5))
    .ContinueWith(t => CheckOnTasks());