【发布时间】:2019-10-08 01:14:26
【问题描述】:
我有以下定期运行的 C# 代码,例如每 1 小时运行一次。每次运行时,它都会尝试并行进行一些远程调用。当这些远程调用中的任何一个引发异常时,我只创建一个票,或更新之前的票。并且在 finally 块中,如果这次没有异常,则解决现有的先前票证。本质上,我想确保无论有多少远程调用失败,我只有一张票可以调查。并且当下次所有调用都成功时,票证会自动解决。
但是,当远程调用在try块中全部成功时,finally块中的调用尝试解析票证,但遇到HTTP 412 Precondition Failed,这意味着我在try块中获得的票证在finally之前以某种方式更新堵塞。如果它在同一个线程中更新,我不会尝试解决它。
我从post 了解到,Task.WhenAll 将等待所有任务完成,即使存在失败(错误或取消的任务)。如果多个任务抛出异常,catch 块会运行一次还是多次? finally 块呢?
Ticket ticket = null;
try
{
// Query to get the existing ticket if there is any.
ticket = await QueryExistingTicketAsync();
// Make a lot of remote calls in parallel
var myTasks = new List<Task>();
myTasks.Add(RemoteCallAsync("call1"));
myTasks.Add(RemoteCallAsync("call2"));
myTasks.Add(RemoteCallAsync("call3"));
// ... add more Tasks for RemoteCallAsync()
await Task.WhenAll(myTasks);
}
catch (Exception ex)
{
if (ticket != null)
{
ticket.ReChecked = true;
ticket.LastCheckTime = DateTimeOffset.Now;
// If the previous ticket exists, meaning the last run failed as well,
// update the timestamp on that ticket.
ticket = await UpdateExistingTicketAsync(ticket);
}
else
{
// If the previous ticket does not exist yet,
// create one ticket for investigation, this ticket.ReChecked will be true
ticket = await CreateNewTicketAsync();
}
}
finally
{
// Resolve the previous ticket if it was not created/updated in catch block
if (ticket != null && !ticket.ReChecked)
{
ticket.Status = "Resolved";
await UpdateExistingTicketAsync(ticket);
}
}
【问题讨论】:
-
它只会运行一次,如果你希望它运行不止一次,请将 try catch finally 放在异步运行的逻辑中。
-
您的问题不清楚。在您发布的代码中只有一个线程。但是你写了诸如“在try 块中运行的多个线程” 之类的东西。这种说法没有任何意义。每个线程都有自己的堆栈,自己的异常处理,因此有自己的 try/catch/finally 块。如果您不确定正确的术语或无法用英语解释您的问题是什么,请修正问题,使其包含一个好的minimal reproducible example,确切地解释该代码的作用,它与你想要什么,以及具体你需要什么帮助。
-
我同意@PeterDuniho,很难按照您提出问题的方式来帮助您。是否有多个线程进入这个
try块然后等待?myTasks是否设置为在后台线程中运行?附带说明一下,我不知道您为什么要在抛出异常时执行看似业务逻辑的操作,但对我来说这是一种代码味道。 -
@PeterDuniho 感谢您的指导,并为造成的混乱道歉。当我输入问题时,我对看到的内容感到困惑。我已经更新了描述和代码示例,并希望澄清一些细节。
-
@V0ldek 添加了我的意图的更多详细信息,我希望在代码因远程调用失败而失败时得到通知,因此我创建了一个“票证”,类似于警报。我会在下次运行成功时自动解决警报,因为如果错误是暂时的,我不想在警报上投入太多精力。
标签: c# multithreading