我如何从以下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)
并发现是真的。我怎么能这样做?
答案 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
,如果确实如此,请确保您的线程不会保存它的工作。
答案 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);
});