简体   繁体   中英

Re-use of concurrently running tasks

Ok, I've changed the question itself because I think it was not very clear.

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

You'll see that I have 2 methods 'LongRunningMethod()' and 'LongRunningMethod2()'. The 'LongRunningMethod' has a sleep of 10 seconds.

Now here's what I would like to achieve.

The parellel foreach should be entered (which is the case), and as soon as I'm in the parallel loop a timer of 5 seconds will start. When those 5 seconds are finished, I want to re-run the parallel loop (I know in this case it's not good because I'm starting a thread while another one is still running.

In the production environment, every task will have a variable called "isRunning" that I will use to see if I can re-run it or not.

I hope that someone can provide me some help with this issue.

Kind regards,

So first off, to have some code run after each tasks ends and do some further processing on that task you want to call ContinueWith on each of those tasks.

To do something 5 minutes after they have all started you can use 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());

Perhaps you can control the flow of your program using a custom state object. This state object would be used in continuation methods to determine which tasks are finished and should be rescheduled.

Sample:

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();
        }
    }
}

Output:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM