Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.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# 如何停止故障块上的处理管道?_C#_Async Await_Task Parallel Library_Tpl Dataflow - Fatal编程技术网

C# 如何停止故障块上的处理管道?

C# 如何停止故障块上的处理管道?,c#,async-await,task-parallel-library,tpl-dataflow,C#,Async Await,Task Parallel Library,Tpl Dataflow,如果其中一个块决定发生错误,阻止下一个块运行,如何停止数据流块的处理。我认为块可以抛出异常,但不确定停止进一步处理管道的正确方法是什么 更新: private async void buttonDataFlow_Click(object sender, EventArgs e) { var cells = objectListView.CheckedObjects.Cast<Cell>().ToList(); if (cells == null) re

如果其中一个块决定发生错误,阻止下一个块运行,如何停止数据流块的处理。我认为块可以抛出异常,但不确定停止进一步处理管道的正确方法是什么

更新:

private async void buttonDataFlow_Click(object sender, EventArgs e)
{
    var cells = objectListView.CheckedObjects.Cast<Cell>().ToList();
    if (cells == null)
        return;

    var blockPrepare = new TransformBlock<Cell, Cell>(new Func<Cell, Task<Cell>>(Prepare),
    new ExecutionDataflowBlockOptions
    {
        BoundedCapacity = 10000,
        MaxDegreeOfParallelism = Environment.ProcessorCount,
    });

    var blockPreparationFeedback = new TransformBlock<Cell, Cell>(new Func<Cell, Task<Cell>>(PreparationFeedback),
    new ExecutionDataflowBlockOptions
    {
        BoundedCapacity = 10000,
        MaxDegreeOfParallelism = Environment.ProcessorCount,
    });

    var blockTestMover = new ActionBlock<Cell>(new Func<Cell, Task>(TestMover),
    new ExecutionDataflowBlockOptions
    {
        BoundedCapacity = 10000,
        MaxDegreeOfParallelism = Environment.ProcessorCount,
    });

    blockPrepare.LinkTo(blockPreparationFeedback, new DataflowLinkOptions { PropagateCompletion = true });
    blockPreparationFeedback.LinkTo(blockTestMover, new DataflowLinkOptions { PropagateCompletion = true });

    foreach (Cell c in cells)
    {
        var progressHandler = new Progress<string>(value =>
        {
            c.Status = value;
        });

        c.Progress = progressHandler as IProgress<string>;
        blockPrepare.Post(c);
    };

    blockPrepare.Complete();
    try
    {
        await blockTestMover.Completion;
    }
    catch(Exception ee)
    {
        Console.WriteLine(ee.Message);
    }

    Console.WriteLine("Done");
}
private async void按钮daflow\u单击(对象发送方,事件参数e)
{
var cells=objectListView.CheckedObjects.Cast().ToList();
如果(单元格==null)
返回;
var blockPrepare=新转换块(新函数(准备),
新的ExecutionDataflowBlockOptions
{
边界容量=10000,
MaxDegreeOfParallelism=Environment.ProcessorCount,
});
var blockPreparationFeedback=新TransformBlock(新函数)(PreparationFeedback),
新的ExecutionDataflowBlockOptions
{
边界容量=10000,
MaxDegreeOfParallelism=Environment.ProcessorCount,
});
var blockTestMover=new ActionBlock(new Func(TestMover)),
新的ExecutionDataflowBlockOptions
{
边界容量=10000,
MaxDegreeOfParallelism=Environment.ProcessorCount,
});
LinkTo(blockPreparationFeedback,新的DataflowLinkOptions{PropagateCompletion=true});
blockPreparationFeedback.LinkTo(blockTestMover,新数据流链接选项{PropagateCompletion=true});
foreach(单元格中的单元格c)
{
var progressHandler=新进度(值=>
{
c、 状态=价值;
});
c、 Progress=progressHandler作为IProgress;
b.员额(c);
};
blockPrepare.Complete();
尝试
{
等待blockTestMover.完成;
}
捕获(异常ee)
{
控制台写入线(ee.Message);
}
控制台。写入线(“完成”);
}
更新2:

    public ITargetBlock<TInput> CreateExceptionCatchingActionBlock<TInput>(
                    Func<TInput, Task> action,
                    Action<Exception> exceptionHandler,
                    ExecutionDataflowBlockOptions dataflowBlockOptions)
    {
        return new ActionBlock<TInput>(async input =>
        {
            try
            {
                await action(input);
            }
            catch (Exception ex)
            {
                exceptionHandler(ex);
            }
        }, dataflowBlockOptions);
    }
public ITargetBlock CreateExceptionCatchingActionBlock(
Func action,
操作异常处理程序,
ExecutionDataflowBlockOptions(数据流块选项)
{
返回新的ActionBlock(异步输入=>
{
尝试
{
等待动作(输入);
}
捕获(例外情况除外)
{
例外处理程序(ex);
}
},dataflowBlockOptions);
}

如果您有一个管道,您可能已经在使用
PropagateCompletion=true
。这意味着,如果管道中的一个块因异常而失败,那么它之后的所有块也将失败

剩下的是停止故障块之前的所有块。为此,您可以等待管道中最后一个块的
完成。如果执行此操作,请调用第一个块上的
Fault()
,使其失败。代码可能如下所示:

// set up your pipeline

try
{
    await lastBlock.Completion;
}
catch (Exception ex)
{
    ((IDataflowBlock)firstBlock).Fault(ex);

    throw; // or whatever is appropriate to propagate the exception up
}

如果您有一个管道,那么您可能已经在使用
PropagateCompletion=true
。这意味着,如果管道中的一个块因异常而失败,那么它之后的所有块也将失败

剩下的是停止故障块之前的所有块。为此,您可以等待管道中最后一个块的
完成。如果执行此操作,请调用第一个块上的
Fault()
,使其失败。代码可能如下所示:

// set up your pipeline

try
{
    await lastBlock.Completion;
}
catch (Exception ex)
{
    ((IDataflowBlock)firstBlock).Fault(ex);

    throw; // or whatever is appropriate to propagate the exception up
}

如果您想要的是块中的异常意味着当前项在管道中继续,但其他项的处理应继续进行而不中断,那么您可以创建一个块,该块在处理成功时生成一个项,但在引发异常时生成零项:

public IPropagatorBlock<TInput, TOutput> CreateExceptionCatchingTransformBlock<TInput, TOutput>(
    Func<TInput, Task<TOutput>> transform,
    Action<Exception> exceptionHandler,
    ExecutionDataflowBlockOptions dataflowBlockOptions)
{
    return new TransformManyBlock<TInput, TOutput>(async input =>
    {
        try
        {
            var result = await transform(input);
            return new[] { result };
        }
        catch (Exception ex)
        {
            exceptionHandler(ex);

            return Enumerable.Empty<TOutput>();
        }
    }, dataflowBlockOptions);
}
public IPropagatorBlock CreateExceptionCatchingTransformBlock(
Func变换,
操作异常处理程序,
ExecutionDataflowBlockOptions(数据流块选项)
{
返回新的TransformManyBlock(异步输入=>
{
尝试
{
var结果=等待转换(输入);
返回新的[]{result};
}
捕获(例外情况除外)
{
例外处理程序(ex);
返回可枚举的.Empty();
}
},dataflowBlockOptions);
}

如果您想要的是块中的异常意味着当前项在管道中继续,但其他项的处理应继续进行而不中断,那么您可以创建一个块,该块在处理成功时生成一个项,但在引发异常时生成零项:

public IPropagatorBlock<TInput, TOutput> CreateExceptionCatchingTransformBlock<TInput, TOutput>(
    Func<TInput, Task<TOutput>> transform,
    Action<Exception> exceptionHandler,
    ExecutionDataflowBlockOptions dataflowBlockOptions)
{
    return new TransformManyBlock<TInput, TOutput>(async input =>
    {
        try
        {
            var result = await transform(input);
            return new[] { result };
        }
        catch (Exception ex)
        {
            exceptionHandler(ex);

            return Enumerable.Empty<TOutput>();
        }
    }, dataflowBlockOptions);
}
public IPropagatorBlock CreateExceptionCatchingTransformBlock(
Func变换,
操作异常处理程序,
ExecutionDataflowBlockOptions(数据流块选项)
{
返回新的TransformManyBlock(异步输入=>
{
尝试
{
var结果=等待转换(输入);
返回新的[]{result};
}
捕获(例外情况除外)
{
例外处理程序(ex);
返回可枚举的.Empty();
}
},dataflowBlockOptions);
}

这意味着取消所有没有问题的工作,甚至是那些工作。我的意思是,我在foreach循环中向管道发布了大量作业,如果其中一个作业出现故障,所有作业都会被取消。前8项(8项,因为我有8个核心CPU)正在运行,其中一项不再继续,其余的正在完成。但除这8项外,其他项目不再处理。如果没有发生异常,则处理所有项目。我在帖子中更新了源代码。@Pablo我想这正是你想要的,“停止管道中的进一步处理”。我想管道是当我用一些输入数据发布一个作业时,然后该作业传递到另一个块,依此类推,根据链接块。如果我只发布一次,那么区块链将按预期取消。但如果我发布多次,那么所有的“帖子”都会被取消,即使是那些毫无例外地运行的帖子。换句话说,如果我将输入数据[1,2,3,4]发布到区块链,并且仅当我发布2时