为什么我的ActionBlock得到一个状态完成没有我设置它?



我一时糊涂,想不出任何合理的解释。也许这里有人能解释一下。

设置:我有一个类,生成大量的工作项计算与ActionBlock。在这一点上,确切的实现是不相关的,但只要稍微改变一下,问题就会出现在另一个数据集上。

这是最初的版本

public static class Setups
{
private struct RunData
{
internal MyClass1 Setup;
internal MyClass2 Positions;
internal string Set;
}
private static readonly ActionBlock<RunData> ParallelWorker = 
new(d => ProcessSetupsAsync(d.Setup, d.Positions, d.Set), 
new ExecutionDataflowBlockOptions 
{ 
BoundedCapacity = Environment.ProcessorCount * 10, 
MaxDegreeOfParallelism = Environment.ProcessorCount, 
SingleProducerConstrained = false 
});
public static async Task GetSetups(ItemType[] bar1Filter, 
ItemType[] bar2Filter, bool sameSet)
{
for (/* do some work*/)
{
foreach (RunData rd in MyMethod1(/*variables*/).Select(final 
=> new RunData { Positions = positions, Set = set, Setup = final }))
{
if (!await ParallelWorker.SendAsync(rd).ConfigureAwait(false))
{
// Fails after running for about 15 minutes
// with ParallelWorker.Complete is true
throw new Exception("xxxxxxxx");
}
}
}
ParallelWorker.Complete();
await ParallelWorker.Completion.ConfigureAwait(false);
}
private static Task ProcessSetupsAsync
(MyClass1 setup, MyClass2 positions, string set)
{
try
{
List<MyClass1> setups = new();
/* Do some work */
return setups.Count > 0 
? LocalAccess.AddSetupAsync(setups) 
: Task.CompletedTask;
}
catch (Exception ex)
{
Console.WriteLine(ex); //<-Never gets hit.
throw;
}

我的第一个猜测是被调用方法内部的异常,但这显然不是情况。

我明白了。并行任务确实在数据库中造成了死锁情况。我在查看数据库锁时注意到。

在VS调试器中,我确实看到了将SendAsync调用更改为

后的SQLExceptions
if (!await ParallelWorker.SendAsync(rd).ConfigureAwait(false))
{
await Task.Delay(TimeSpan.FromSeconds(60D)).ConfigureAwait(false);
throw new Exception("Should never happen");
}

并在throw new Exception行设置断点。为什么SqlException没有被try/catch捕获,我不知道。所以现在我很困惑,我对try/catch机制的信仰正在崩溃,但我现在在正确的轨道上。

我可以确认如果我序列化db调用错误消失。我现在正在分析数据库,因为我的印象是,在ROW_LOCK场景中,我的数据写入不应该重叠,另一方面,有一个StoredProcedure使用MERGE,这是已知的问题…

原来的问题解决了,但是为什么try/catch没有捕捉到一个简单的SqlException呢?

相关内容

最新更新