Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Factory.StartNew(someMethod(withParam)).continueWith(sameMethod(differentParam)).Wait()

What is the correct syntax for parallelizing the following code?

static void Main(string[] args)
{
    Task.Factory.StartNew(
        () =>
            doOne(SelectedTask.option1)
           .ContinueWith(
            task => 
            doOne(SelectedTask.option1)).Wait()
   ); 
}

Same method with enum "selectedTask" to decide which code to execute :

static enum SelectedTask
{
    option1,
    option2
}

static void doOne(SelectedTask Lunch)
{ 
    switch (lunch)
    {
        case SelectedTask.option1:
            Console.WriteLine("option1");
            break;
        case SelectedTask.option2:
            Console.WriteLine("option2");
            break;
        default:
            break;
    }
}
like image 272
LoneXcoder Avatar asked Nov 20 '12 21:11

LoneXcoder


2 Answers

Do you want your doOne calls to occur concurrently? Then you can just start them straight from the task factory:

// Start two concurrent tasks
var task1 = Task.Factory.StartNew(() => doOne(SelectedTask.option1));
var task2 = Task.Factory.StartNew(() => doOne(SelectedTask.option2));

// Block the current thread until all tasks complete
Task.WaitAll(task1, task2);

Do you want your doOne calls to occur sequentially? Then you can chain them using ContinueWith:

// Start a chain of tasks
var task1 = Task.Factory.StartNew(() => doOne(SelectedTask.option1));
var task2 = task1.ContinueWith(t => doOne(SelectedTask.option2));

// Block the current thread until the last task completes
task2.Wait();

The code in the title of your post (with a couple of fixes) is essentially performing the exact same function as my sequential task chain above:

Task.Factory.StartNew(() => doOne(SelectedTask.option1))
            .ContinueWith(t => doOne(SelectedTask.option2))
            .Wait();

Answer to your question below.

If I understand correctly, you want to be able to run a task for a variable list of SelectedTasks in parallel:

List<SelectedTask> selectedTaskOptions = new List<SelectedTask>()
{
    SelectedTask.option1,
    SelectedTask.option2,
    SelectedTask.option3,
    SelectedTask.option4,
    SelectedTask.option5
};

RunAllSelectedTaskOptions(selectedTaskOptions);

RunAllSelectedTaskOptions to accept and run a list of SelectedTasks:

public void RunAllSelectedTaskOptions(List<SelectedTask> selectedTaskOptions)
{
    List<Task> createdTasks = new List<Task>();

    foreach(var taskOption in selectedTaskOptions)
    {
        createdTasks.Add(Task.Factory.CreateNew(() => doOne(taskOption)));
    }

    Task.WaitAll(createdTasks);
}

Another way of implementing RunAllSelectedTaskOptions would be to use Parallel.ForEach, which will execute in parallel and will block until the slowest/last iteration has completed:

public void RunAllSelectedTaskOptions(List<SelectedTask> selectedTaskOptions)
{
    Parallel.ForEach(selectedTaskOptions, taskOption => doOne(taskOption));
}
like image 156
Dave New Avatar answered Oct 05 '22 09:10

Dave New


I assume you are talking about parallelizing the two doOne calls?

If so, then you will need to do something like this:

var task1 = Task.Factory.StartNew(() => doOne(SelectedTask.option1));
var task2 = Task.Factory.StartNew(() => doOne(SelectedTask.option2));
var taskList = new List<Task>{task1, task2};
Task.WaitAll(taskList);

*The above code is fairly accurate but the syntax has not been validated.

like image 41
Justin Pihony Avatar answered Oct 05 '22 07:10

Justin Pihony