如何停止Parallel.ForEach的所有执行线程?

时间:2012-10-04 10:03:02

标签: c# task-parallel-library

我如何从以下Parallel.ForEach循环中解脱出来......

Parallel.ForEach(
                    webnode.ChildNodes.OfType<XmlNode>(),
                    (node,loopState) =>
                        {
                            if(threadCommand!=null &&                   threadCommand.CurrentSubIndicator.StopSignaled)
                                loopState.Stop();

                            string title = node.Attributes["Title"].Value;
                            string url = node.Attributes["Url"].Value;
                            if (!string.IsNullOrEmpty(specificItemUrl) &&
                                (!url.Equals(specificItemUrl)))
                                return;
                            Site partialSubSite = new WSS(site, Guid.Empty, title, url, "", null, null);

                            try
                            {
                                GetSite(partialSubSite, lite, readNavigation);
                            }
                            catch (Exception ex)
                            {
                                LogERError("Failed to fully read sub-site: {0}", url, ex);
                                partialSubSite.Guid = Constants.BadItemId;
                            }


                        });

我想在检查条件后退出所有线程以停止执行 if (threadCommand!=null && threadCommand.CurrentSubIndicator.StopSignaled)并发现是真的。我怎么能这样做?

4 个答案:

答案 0 :(得分:2)

你无法立即停止它们。取消是合作的。您的线程需要定期检查取消合作。没有其他办法,因为只是在一些不适用的情况下杀死工作线程。

答案 1 :(得分:1)

检查TPL的CancellationTokens。 http://blogs.msdn.com/b/pfxteam/archive/2009/06/22/9791840.aspx 将CancellationToken传递给Parallel.Foreach()可以使它工作。当您想要停止所有任务时,只需使用:

cts.Cancel()

在Task的方法位置

 cts.Token.ThrowIfCancellationRequested(); 

当您想检查是否需要停止任务时,因为另一个任务取消了该过程。

这是一个未经测试的如何使用它的例子:

CancellationTokenSource cts = new CancellationTokenSource(); 
ParallelOptions options = new ParallelOptions 
                             {CancellationToken = cts.Token}; 

Parallel.ForEach(
                webnode.ChildNodes.OfType<XmlNode>(),
                 options 
                (node,loopState) =>
                    {

                        if(threadCommand!=null &&                   threadCommand.CurrentSubIndicator.StopSignaled)
                            cts.Cancel();

                        string title = node.Attributes["Title"].Value;
                        string url = node.Attributes["Url"].Value;
                        if (!string.IsNullOrEmpty(specificItemUrl) &&
                            (!url.Equals(specificItemUrl)))
                            return;
                        cts.Token.ThrowIfCancellationRequested();
                        Site partialSubSite = new WSS(site, Guid.Empty, title, url, "", null, null);

                        try
                        {
                            GetSite(partialSubSite, lite, readNavigation);
                        }
                        catch (Exception ex)
                        {
                            LogERError("Failed to fully read sub-site: {0}", url, ex);
                            partialSubSite.Guid = Constants.BadItemId;
                        }


                    });

答案 2 :(得分:0)

我发现这篇文章,它解决了使用ParallelLoopState.Stop()ParallelLoopState.Break()之间的区别。它似乎暗示虽然线程可以继续工作,但您可以检查ParallelLoopState.IsStopped,如果确实如此,请确保您的线程不会保存它的工作。

http://msdn.microsoft.com/en-us/library/dd460721.aspx

答案 3 :(得分:0)

我可以像这样使用

 Parallel.ForEach(
                    webnode.ChildNodes.OfType<XmlNode>(),
                   (node, loopState) =>
                    {
                        if (threadCommand != null && threadCommand.CurrentSubIndicator.StopSignaled)
                            loopState.Stop();

                        string title = node.Attributes["Title"].Value;
                        string url = node.Attributes["Url"].Value;
                        if (!string.IsNullOrEmpty(specificItemUrl) &&
                            (!url.Equals(specificItemUrl)))
                            return;


                        if (loopState.IsStopped)
                            loopState.Break();

                        Site partialSubSite = new WSS(site, Guid.Empty, title, url, "", null, null);

                        try
                        {
                            if (loopState.IsStopped)
                                loopState.Break();

                            GetSite(partialSubSite, lite, readNavigation);
                        }
                        catch (Exception ex)
                        {
                            LogERError("Failed to fully read sub-site: {0}", url, ex);
                            partialSubSite.Guid = Constants.BadItemId;
                        }

                        if (partialSubSite.Web.IsBucketWeb)
                        {
                            lock (others)
                                others.AddRange(partialSubSite.Web.SubWebUrls.Cast<string>());
                            return;
                        }
                        lock (subSites)
                            subSites.Add(partialSubSite as WSS);
                    });