线程 - 谋杀儿童 [英] Threads - Murdering Children

查看:112
本文介绍了线程 - 谋杀儿童的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个生成大素数的方法(可能)。部分过程是确定测试是否表明数字是复合的。你做的测试越多,你就越有把握,这个数字是素数,但是如果任何单个测试返回
'Compound'那么你就完成了,这个数字肯定是复合的。为了加快测试,我在子线程中同时运行复合测试。由于所有测试花费的时间大约相同,所以让所有
子线程自行消失并不是一个大问题,但如果不是这样的话呢?在离开方法并进入下一个素数测试之前,如何清理不需要的子线程?

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是最小素数的大数组。
if(n == primeArray [x])返回true;
if(n%primeArray [x] == 0)返回false;
}
if(n< primeArray [1022] * primeArray [1022])返回true;
BigInteger s = n - 1;
而(s.IsEven)
{
s>> = 1;
}
BigInteger mod = 0;
bool IsComposite = false,alldone = false;
DelCompWitness delCompWitness = CompositeFinder;
arrayofa [0] = 0; //将第一个值设置为2,最有可能快速显示复合属性
ar [0] =(AsyncResult)delCompWitness.BeginInvoke(2,s,n,out threadIDs [0],null,null);
arrayofa [1] = 1; //将第二个值设置为3,更有可能快速显示复合属性
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很糟糕,需要重做这个。
{
IsComposite = delCompWitness.EndInvoke(out threadIDs [i],ar [i]);
}
其他
{
alldone = false;
}
}
}
}
返回!IsComposite;
}

// 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; }

推荐答案

我不会使用线程。我个人会为每个孩子的工作创建一个任务。创建一个CancellationTokenSource并在启动时将CancellationToken从它传递给每个任务。当您决定完成后,取消令牌。在您的任务函数
内,您需要定期检查取消。当您检测到取消时,它会抛出一个终止任务的异常。因此所有任务都取消。

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}正在等待...");

//检查取消
cancellationToken.ThrowIfCancellationRequested();
};

Console.WriteLine(
"Task {someValue} is waiting..."); //Check for cancellation cancellationToken.ThrowIfCancellationRequested(); }; Console.WriteLine(


" Task {someValue} completed");
}
"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.

如果由于某种原因线程不会终止,那么你最终可以杀死它,但你必须保持Thread对象这样做。

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.


这篇关于线程 - 谋杀儿童的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆