Stevie Wonder
Stevie Wonder

Reputation: 129

Multi threading a single repetitive task

I have a console application that generates(solves) a valid sudoku puzzle from n number of clues but the way I currently have it setup is that my method is called over and over until a valid solution is found. Is this the correct way to implement multi-threading when wanting to run the same function over and over? Or is their another way better way. Appreciate any help!

*GenerateBoard() returns a multidimensional array

bool valid = false;

while (valid == false)
            {
            var task1 = Task.Factory.StartNew(() => GenerateBoard());
            var one = ValidateSolution(task1.Result);
            if (one) { valid = true; } else { Console.WriteLine("Task1 trying again"); }

            var task2 = Task.Factory.StartNew(() => GenerateBoard());
            var two = ValidateSolution(task2.Result);
            if (two) { valid = true; } else { Console.WriteLine("Task2 trying again"); }

            var task3 = Task.Factory.StartNew(() => GenerateBoard());
            var three = ValidateSolution(task3.Result);
            if (three) { valid = true; } else { Console.WriteLine("Task3 trying again"); }

            var task4 = Task.Factory.StartNew(() => GenerateBoard());
            var four = ValidateSolution(task4.Result);
            if (four) { valid = true; } else { Console.WriteLine("Task4 trying again"); }}

Upvotes: 0

Views: 71

Answers (1)

Kevin Gosse
Kevin Gosse

Reputation: 39007

You can abuse Parallel Linq to search your solutions in parallel:

IEnumerable<object> InfiniteEnumerable()
{
    while (true) yield return null;
}

var result = InfiniteEnumerable()
    .AsParallel()
    .Select(_ => GenerateBoard())
    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
    .AsSequential()
    .First(ValidateSolution);

This will automatically use the optimal number of threads for your hardware.

The .WithMergeOptions(ParallelMergeOptions.NotBuffered) and .AsSequential() are important to make sure that the processing stops as soon as the first solution is found. As for the InfiniteEnumerable(), I don't know if there's a smarter way to tell PLinq to keep processing until the first valid result.

Upvotes: 1

Related Questions