为什么有时 ActionBlock 中的 Try/catch 没有捕捉到这个错误?
Why does Try/catch in ActionBlock not catch this error sometimes?
我正在编写的网络爬虫中使用 ActionBlock。
有时我打电话给
actionBlock.Completion.Wait();
我收到以下错误
One or more errors occurred.
内部例外是
System.Threading.Tasks.TaskCanceledException: A task was canceled.
这是下面的完整代码块。
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
全部内容的 try/catch 没有捕捉到这个异常?
在进入try之前开始动作,会不会异常发生的太早了?
将 actionBlock.Post(new URLsToCheckObject { URLAddress = WebsiteToCrawl.website, Host = host });
移到 try catch
内
ActionBlock<>
可以安排处理您 Post
处理的所有项目。因此,要执行的代码比您在 lambda 中实现的要多。 (就像 Parallel.ForEach
或 Task.Run()
比您传递的代码要执行的更多)。
ActionBlock<>
必须等待传入的元素,因此还要检查是否应该取消它。即使有传入的项目,它也会检查是否在调用您的代码之前请求取消,因此在您的try
块之外。
因此,如果在块仅等待项目时请求取消,但当前未在您的 lambda 中处理项目,则您无法捕获异常。
异常通常来自:
cancellationToken.ThrowIfCancellationRequested();
因为您没有在 lambda 中使用 CancellationToken
,但它用作以下参数:
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 3, CancellationToken = cancellationSource.Token }
TaskCanceledException
不是来自你的 lambda(但可能来自 ExecutionDataflowBlockOptions
或 ActionBlock
内部)所以它在你的 try/catch 范围之外lambda,所以它没有捕获。
我正在编写的网络爬虫中使用 ActionBlock。
有时我打电话给
actionBlock.Completion.Wait();
我收到以下错误
One or more errors occurred.
内部例外是
System.Threading.Tasks.TaskCanceledException: A task was canceled.
这是下面的完整代码块。
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
全部内容的 try/catch 没有捕捉到这个异常?
在进入try之前开始动作,会不会异常发生的太早了?
将 actionBlock.Post(new URLsToCheckObject { URLAddress = WebsiteToCrawl.website, Host = host });
移到 try catch
ActionBlock<>
可以安排处理您 Post
处理的所有项目。因此,要执行的代码比您在 lambda 中实现的要多。 (就像 Parallel.ForEach
或 Task.Run()
比您传递的代码要执行的更多)。
ActionBlock<>
必须等待传入的元素,因此还要检查是否应该取消它。即使有传入的项目,它也会检查是否在调用您的代码之前请求取消,因此在您的try
块之外。
因此,如果在块仅等待项目时请求取消,但当前未在您的 lambda 中处理项目,则您无法捕获异常。
异常通常来自:
cancellationToken.ThrowIfCancellationRequested();
因为您没有在 lambda 中使用 CancellationToken
,但它用作以下参数:
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 3, CancellationToken = cancellationSource.Token }
TaskCanceledException
不是来自你的 lambda(但可能来自 ExecutionDataflowBlockOptions
或 ActionBlock
内部)所以它在你的 try/catch 范围之外lambda,所以它没有捕获。