C# 为什么ActionBlock中的Try/catch有时无法捕获此错误?
我在写的网络爬虫中使用了ActionBlock 有时候我打电话的时候C# 为什么ActionBlock中的Try/catch有时无法捕获此错误?,c#,task-parallel-library,tpl-dataflow,C#,Task Parallel Library,Tpl Dataflow,我在写的网络爬虫中使用了ActionBlock 有时候我打电话的时候 actionBlock.Completion.Wait(); 我得到以下错误 发生了一个或多个错误 内部的例外是 System.Threading.Tasks.TaskCanceledException:任务已取消 这是下面的完整代码块 actionBlock = new ActionBlock<URLsToCheckObject>(URLToCheck => { try {
actionBlock.Completion.Wait();
我得到以下错误
发生了一个或多个错误
内部的例外是
System.Threading.Tasks.TaskCanceledException:任务已取消
这是下面的完整代码块
actionBlock = new ActionBlock<URLsToCheckObject>(URLToCheck =>
{
try
{
// get more urls etc here and post below
actionBlock.Post(new URLsToCheckObject { URLAddress = CleanURL, Host = host });
if (actionBlock.InputCount == 0) actionBlock.Complete();
}
catch (Exception ex)
{
try
{
Logger.AddToDebugLog("Block 3 catch...", WebsiteToCrawl);
}
catch { }
}
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 3, CancellationToken = cancellationSource.Token });
actionBlock.Post(new URLsToCheckObject { URLAddress = WebsiteToCrawl.website, Host = host });
try
{
Logger.AddToDebugLog("Waiting on action block..", WebsiteToCrawl);
actionBlock.Completion.Wait();
}
catch (Exception ex)
{
try
{
Logger.AddToDebugLog("Block 4 catch..." + ex.Message, WebsiteToCrawl);
}
catch { }
try
{
Logger.AddToDebugLog("Block 4 catch..." + ex.InnerException, WebsiteToCrawl);
}
catch { }
try
{
Logger.AddToDebugLog("Block 4 catch...", WebsiteToCrawl);
}
catch { }
}
actionBlock=newactionblock(URLToCheck=>
{
尝试
{
//在这里获取更多URL等,并在下面发布
Post(新的URLsToCheckObject{URLAddress=CleanURL,Host=Host});
如果(actionBlock.InputCount==0)actionBlock.Complete();
}
捕获(例外情况除外)
{
尝试
{
Logger.AddToDebugLog(“块3捕获…”,WebsiteToCrawl);
}
捕获{}
}
},新的ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=3,CancellationToken=cancellationSource.Token});
actionBlock.Post(新的URLsToCheckObject{URLAddress=WebsiteToCrawl.website,Host=Host});
尝试
{
AddToDebugLog(“等待操作块…”,WebsiteToCrawl);
actionBlock.Completion.Wait();
}
捕获(例外情况除外)
{
尝试
{
Logger.AddToDebugLog(“块4捕获…”+例如消息,WebsiteToCrawl);
}
捕获{}
尝试
{
Logger.AddToDebugLog(“块4捕获…”+ex.InnerException,WebsiteToCrawl);
}
捕获{}
尝试
{
AddToDebugLog(“块4捕获…”,WebsiteToCrawl);
}
捕获{}
}
为什么包装
ActionBlock
全部内容的try/catch无法捕获此异常?当您在进入try之前启动操作时,是否可能异常发生得太快
Move
actionBlock.Post(新的URLsToCheckObject{URLAddress=WebsiteToCrawl.website,Host=Host})代码>在try catch
中当您在进入try之前启动操作时,是否可能异常发生得太快
MoveactionBlock.Post(新的URLsToCheckObject{URLAddress=WebsiteToCrawl.website,Host=Host})代码>在try catch
中ActionBlock
用于计划处理您发布到的所有项目。因此,要执行的代码比在lambda中实现的代码要多。(就像Parallel.ForEach
或Task.Run()
要执行的代码比传递的代码多)
ActionBlock
必须等待传入元素,从而检查是否应该取消它。即使有传入项目,它也会在调用代码之前检查是否已请求取消,因此超出了try
块
因此,如果在块仅等待项目,但当前未处理lambda中的项目时请求取消,则无法捕获异常。ActionBlock
用于安排处理您发布的所有项目。因此,要执行的代码比在lambda中实现的代码要多。(就像Parallel.ForEach
或Task.Run()
要执行的代码比传递的代码多)
ActionBlock
必须等待传入元素,从而检查是否应该取消它。即使有传入项目,它也会在调用代码之前检查是否已请求取消,因此超出了try
块
因此,如果在块仅等待项目而当前未处理lambda中的项目时请求取消,则无法捕获异常。异常通常来自:
cancellationToken.ThrowIfCancellationRequested();
由于您没有在lambda中使用CancellationToken
,但它被用作以下各项的参数:
new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=3,CancellationToken=cancellationSource.Token}
TaskCanceledException
不是来自lambda(但可能来自ExecutionDataflowBlockOptions
或ActionBlock
)的内部),因此它不在lambda内部的try/catch范围内,因此不会捕获。异常通常来自:
cancellationToken.ThrowIfCancellationRequested();
由于您没有在lambda中使用CancellationToken
,但它被用作以下各项的参数:
new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=3,CancellationToken=cancellationSource.Token}
TaskCanceledException
不是来自lambda(但可能来自ExecutionDataflowBlockOptions
或ActionBlock
)的内部),因此它不在lambda内部的try/catch范围内,因此它不被捕获。您正在操作内部的委托。我不认为这个类被设计成这样使用。如果您想创建一个循环,其中管道末端将向管道添加更多元素,您可能应该在ActionBlock
之前使用一个linked,并将ActionBlock
发布到BufferBlock
@jamie,这不是数据流块的工作方式。这段代码本质上是一个无限循环,它将ActionBlock视为一个队列。您不会告诉块从内部完成,它会在上游块完成时自动完成。如果要生成更多URL,请在上一步中进行。代码根本不必如此复杂,因为您正在自己的委托内部操作。我不认为这个类被设计成这样使用。如果要在管道末端向管道添加更多元素的位置创建循环,可能应该在ActionBlock
之前使用链接,并将ActionBlock
发布到BufferB