Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么ActionBlock中的Try/catch有时无法捕获此错误?_C#_Task Parallel Library_Tpl Dataflow - Fatal编程技术网

C# 为什么ActionBlock中的Try/catch有时无法捕获此错误?

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

有时候我打电话的时候

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之前启动操作时,是否可能异常发生得太快

Move
actionBlock.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