重用并发运行的任务

时间:2014-04-16 13:39:14

标签: c# parallel-processing

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

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.");
}

你会看到我有2个方法'LongRunningMethod()'和'LongRunningMethod2()'。 'LongRunningMethod'睡眠时间为10秒。

现在这就是我想要实现的目标。

应该输入parellel foreach(在这种情况下),并且一旦我进入并行循环,将启动5秒的计时器。当这5秒钟完成后,我想重新运行并行循环(我知道在这种情况下它不好,因为我正在启动一个线程而另一个仍在运行。

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

我希望有人可以帮我解决这个问题。

亲切的问候,

2 个答案:

答案 0 :(得分:1)

首先,要在每个任务结束后运行一些代码,并对该任务进行一些进一步处理,以便在每个任务上调用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());

答案 1 :(得分:1)

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

样品:

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
...