【问题标题】:How to keep ActionBlock running on any exception如何在任何异常情况下保持 ActionBlock 运行
【发布时间】:2017-07-19 08:14:35
【问题描述】:

我有一个ActionBlock,它简单地连续处理来自无限循环的消息。在ActionBlock 里面我发了一个http 帖子。当出现任何与网络相关的错误时,该方法会引发异常并且块出现故障/停止。这不是我想要的行为。即使发生异常,我也希望处理运行。 (继续打Process方法)来模拟我的程序;

private static ExecutionDataflowBlockOptions processBlockOptions
{
    get
    {
        return new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = 1
        };
    }
}

static async Start()
{
    processQueue = new 
        ActionBlock<QueueMessage>(
            async (item) =>
            {
                await Process(item);
            },
            processBlockOptions); 

    while (!Stopped)
    {
       //Read from DB and do logic with item
       QueueMessage item= new QueueMessage();
       await processQueue.SendAsync(item);                              
    }
}    

private async static Task<int> Process(QueueMessage item)
{
    try
    {
        await item.HttpPost(order);
    }
    catch (Exception ex)
    {
        //Http endpoint might be broken
        throw ex;
    }
}

【问题讨论】:

  • 尝试只记录错误而不是使用throw ex。抛出将停止工作流程。
  • 你想要什么行为?当异常发生时你希望发生什么?你打算忽略它吗?然后不要像 Nico 说的那样重新抛出异常。你现在做的方式不应该捕获异常,因为它无助于隐藏实际的堆栈跟踪。
  • 你说得对,我完全忘记了 throw ex 行,当我改变它时,代码开始流动。
  • Stephen Cleary 的可爱的小Try 库允许处理所有消息,最后得到结果或在执行每条消息期间发生的异常。您所要做的就是将每条消息包装在 Try&lt;T&gt; 包装器中。

标签: c# async-await task task-parallel-library tpl-dataflow


【解决方案1】:

你重新抛出你的异常,你做错了:

throw ex;

如果您需要记录错误或停止管道一段时间,您无需抛出任何东西,只需记录 ex.ToString() 并做出相应反应。第二件事是您应该使用throw; 而不是throw ex;,因为您正在为异常重写堆栈跟踪,这在这种情况下并不重要,但在更复杂的工作流程中可能会产生误导。

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 2017-06-05
    • 2015-05-08
    • 2018-09-23
    • 2016-05-23
    • 2019-12-06
    相关资源
    最近更新 更多