none
Threads - Murdering Children RRS feed

  • Question

  • I have a method that generates large prime numbers (probably). Part of the process is to determine if a test indicates that a number is composite. The more tests that you do, the more assured you can be that the number is prime but if any single test returns 'Composite' then you are done, the number is definitely composite. To expedite the test, I run the composite tests simultaneously in child threads. Since all the tests take about the same amount of time to complete, it's not such a big issue to let all the child threads die off on their own but what if that wasn't the case? How could I clean up the unneeded child threads before I leave the method and move onto the next prime number test?

    public static bool IsProbablyPrime(BigInteger n, int k) { AsyncResult[] ar = new AsyncResult[k]; int[] threadIDs = new int[k]; int[] arrayofa = new int[k]; // int limit = primeArray.GetUpperBound(0), a; int limit = 50, a; if (n < 2) { return false; } if (n < 4) { return true; } for (int x = 0; x < 1023; x++) {

    // primeArray is a large array of the smallest prime numbers. if (n == primeArray[x]) return true; if (n % primeArray[x] == 0) return false; } if (n < primeArray[1022] * primeArray[1022]) return true; BigInteger s = n - 1; while (s.IsEven) { s >>= 1; } BigInteger mod = 0; bool IsComposite = false, alldone = false; DelCompWitness delCompWitness = CompositeFinder; arrayofa[0] = 0; // Set first value to 2, most likely to reveal a composite property quickly ar[0] = (AsyncResult)delCompWitness.BeginInvoke(2, s, n, out threadIDs[0], null, null); arrayofa[1] = 1; // Set second value to 3, more likely to reveal a composite property quickly ar[1] = (AsyncResult)delCompWitness.BeginInvoke(3, s, n, out threadIDs[1], null, null); for (int i = 2; i < k; i++) { a = rndNum.Next(2, limit); while (primeArray[arrayofa[i]] >= n - 1 || arrayofa.Contains(a)) { a = rndNum.Next(2, limit); } arrayofa[i] = a; ar[i] = (AsyncResult)delCompWitness.BeginInvoke(primeArray[arrayofa[i]], s, n, out threadIDs[i], null, null); } while (!IsComposite && !alldone) { alldone = true; for (int i = 0; i < k && !IsComposite; i++) { if (!ar[i].EndInvokeCalled) { if (ar[i].AsyncWaitHandle.WaitOne(15)) // polling sucks, need to rework this. { IsComposite = delCompWitness.EndInvoke(out threadIDs[i], ar[i]); } else { alldone = false; } } } } return !IsComposite; }


    Saturday, December 30, 2017 3:14 PM

All replies

  • I wouldn't use threads. Personally I would create a Task for each child work. Create a CancellationTokenSource and pass the CancellationToken from it to each of the tasks when it starts. When you decide you're done, cancel the token. Inside your task function you need to periodically check for cancellation. When you detect cancellation then it throws an exception which terminates the task. Hence all the tasks cancel.

    static void Main ( string[] args )
    {            
        var cancellationSource = new CancellationTokenSource();
    
        //If user presses Ctrl+C then cancel the running work
        Console.CancelKeyPress += (o, e) => cancellationSource.Cancel();
    
        //TODO: Whatever task(s) you want to run async
        var tasks = new List<Task>();
        for (var index = 0; index < 10; ++index)
        {
            tasks.Add(DoLongWorkAsync(index, cancellationSource.Token));
        };
    
        //Wait until everything completes
        try
        {
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("All tasks completed");
        } catch (AggregateException e) when (e.InnerException is OperationCanceledException)
        {
            Console.WriteLine("Tasks cancelled");
        };
    
        Console.ReadLine();
    }
    
    static async Task DoLongWorkAsync ( int someValue, CancellationToken cancellationToken )
    {
        //Emulate the lengthy work here using a looping construct
        for (var index = 0; index < someValue; ++index)
        {
            //Time consuming work
            await Task.Delay(1000).ConfigureAwait(false);
    
            Console.WriteLine($"Task {someValue} is waiting...");
    
            //Check for cancellation
            cancellationToken.ThrowIfCancellationRequested();
        };
    
        Console.WriteLine($"Task {someValue} completed");
    }

    You can do something similar with threads but you'll have to create a termination event. Inside each thread function periodically check for this event. Set the event when you want to cancel all the threads. Basically it works like tasks but requires more code.

    If for some reason a thread won't terminate then you ultimately can kill it but you have to keep the Thread object around to do that.


    Michael Taylor http://www.michaeltaylorp3.net

    Saturday, December 30, 2017 4:56 PM
    Moderator
  • For each thread create an AutoResetEvent and each thread can check it occasionally. Then when you need to stop a thread just "Set" the event to signaled.

    Or for your requirements you probably need just one event that all the threads check and when the main thread signals the event all threads return.



    Sam Hobbs
    SimpleSamples.Info

    Monday, January 1, 2018 10:34 AM
  • If you start using threads, you should first ask yourself: "Do I need them". Be aware somewhere multiple threads are processed so they have a longer actual processing time then one thread. Also be aware that threading in .Net is not the same as using a multi core processor. 

    Threading in .Net is using more task processes which also can be done with a single core processor. 

     

    Success Cor


    Monday, January 1, 2018 11:26 AM
  • If you start using threads, you should first ask yourself: "Do I need them". Be aware somewhere multiple threads are processed so they have a longer actual processing time then one thread. Also be aware that threading in .Net is not the same as using a multi core processor. 

    Threading in .Net is using more task processes which also can be done with a single core processor. 

     

    Success Cor


    I am not sure I understand what you are saying. You seem to be saying that .Net can use only one core at a time. See the following.

    They indicate that .Net can use multiple cores. Also see Parallel Programming in .NET | Microsoft Docs; it seems especially clear.



    Sam Hobbs
    SimpleSamples.Info

    Tuesday, January 2, 2018 12:58 AM
  • If you start using threads, you should first ask yourself: "Do I need them". Be aware somewhere multiple threads are processed so they have a longer actual processing time then one thread. Also be aware that threading in .Net is not the same as using a multi core processor. 

    Threading in .Net is using more task processes which also can be done with a single core processor. 

     

    Success Cor


    I am not sure I understand what you are saying. You seem to be saying that .Net can use only one core at a time. See the following.

    They indicate that .Net can use multiple cores. Also see Parallel Programming in .NET | Microsoft Docs; it seems especially clear.



    Sam Hobbs
    SimpleSamples.Info

    Sorry Sam, I use a kind of English with the word "also". It does in my English not mean "not" but is a synonym for "as well" and "too"

    However, maybe does this sentence copied from one of your links (2 are just forums links) tell in other words what I wanted to tell in my message with less words. 

    Threads

    Because you are using threads, doesn’t mean you are doing multi-core programming.  Use would use threads when you want to have your user interface continue even while it would otherwise be blocked waiting for a compute or I/O-heavy response. So they work on a single core machine.

    But they have a cost. And that cost means that if you have thousands of methods that do computing, it will bring a computer to its knees or crash.




    Success Cor



    Thursday, January 4, 2018 8:15 PM