Click here to Skip to main content
15,885,365 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a method that verifies if one condition is valid. But this verification is a little heavy. So, I need to verify this with parallel taks, when anyone this verification stop then I cancel all the others tasks. So, I need to verify this with parallel tasks, when some those verification has finished first then I'll cancel all the others tasks. And returne the results.
To be more clear, I'll execute this verification with only one method but passing different values. The call which return me first I'll cancel the others parallels tasks.

What I have tried:

I have tried this operation with simple thread, but it doesn't work well.
Posted
Updated 26-Feb-16 14:50pm
Comments
Matt T Heffron 18-Feb-16 21:26pm    
So your method verifies one aspect of the overall state. Is success if ALL aspects are "valid", so you want to stop any verifications still in progress as soon as one FAILS, but continue to completion as long as they are "passing"?
OR do you just want to start a bunch of verifications in parallel and as soon as ANY complete (pass or fail) then cancel all N-1 of the still in progress verifications?
Paulo César R. Gonçalves 19-Feb-16 6:34am    
I'll try to explain more my problem. I have a list of server and domains and also I have a login and password.
I need to verify if this login and password works in anyone those servers.
For that, I need to verify this using tasks parallel. Which one that return true first, i'll cancel the others tasks.
Those tasks will call the same method, but with servers and domains different.
This verification sometimes is a little heavy for that reason I need to use threads or tasks etc.

And one more thing, the tasks needs to be created dynamically according of numbers of servers/domains.

I have a solution, but the code is ugly and big.
Matt T Heffron 27-Apr-16 20:57pm    
Paulo, Did you solve this?
I posted a Solution a couple of months ago and I'm wondering if it helped...

When I first saw this question I thought of Reactive Extensions (Rx)[^]
It took a while to get a chance to work it up, but here is an example where each (proxy for a) query of the server/domain is done in parallel in a separate Task and Rx is used to wait for the first one that returns true. Once success happens, then the CancellationToken is used to notify any query that hasn't completed that it can quit. (I'm assuming that your verification method can use a CancellationToken to stop before completing.)
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication7
{
  class Program
  {
    static  void Main(string[] args)
    {
      RunIt();
      Console.ReadLine();
    }

    // This is so the individual queries can return both the status and 
    // something that identifies the input(s) that led to that succuss/fail
    private class Result
    {
      public readonly int Id;
      public bool Success { get; set; }
      public Result(int id)
      {
        Id = id;
        Success = false;
      }
    }
    static async void RunIt()
    {
      CancellationTokenSource cancellationSource = new CancellationTokenSource();
      CancellationToken token = cancellationSource.Token;
      // this List<int> values is the "proxy" for your set of server/domain
      // if in your case the servers & domains are independent vs. paired
      // then constructing the observableValues will be a bit trickier. :-)
      Random rand = new Random();
      List<int> values = Enumerable.Range(0, 10).Select(_ => rand.Next(1, 30)).ToList(); // ensure the values are "locked"
      Console.WriteLine("values=");
      foreach (var item in values)
      {
        Console.WriteLine(item);
      }
      Console.WriteLine();
      var observableValues = values.ToObservable();
      var tasks = observableValues.Select(x => Task.Run<Result>(() => {
        // This proxy for your validation "query" here just waits for the specified number of seconds, checking for cancellation each second
        // This is to simulate the queries each taking differing amounts of time
        Console.WriteLine("Start " + x.ToString());
        var res = new Result(x);
        for (int i = 0; i < x; i++)
        {
          if (token.IsCancellationRequested)
          {
            Console.WriteLine("Cancellation requested: {0}", x);
            return res;
          }
          Thread.Sleep(1000);
        }
        Console.WriteLine("Task = " + x.ToString());
        res.Success = (x & 1) != 0;   // Here the proxy for your validation success/failure is just that the input x is odd!
        return res;
      }, token));
      // by passing the token to the Task.Run() if cancellation happens before some Tasks get started, they just won't start at all

      // The Tasks don't actually start getting spun up until here:
      Result found = await tasks.Merge().FirstOrDefaultAsync(r => r.Success);
      cancellationSource.Cancel();
      Console.WriteLine(found == null ? "None found" : ("Found " + found.Id.ToString()));
    }
  }
}
 
Share this answer
 
Take a look at Parallel.ForEach Method:
C#
Parallel.ForEach(myTasks, t => t.DoSomethingInBackground());

Console.Write("All tasks Completed. Now we can do further processing");
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900