一时百思不得其解,想不出什么合理的解释。也许这里有人有解释。
设置: 我有一个生成大量工作项的类,需要使用
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 机制的信念正在崩溃,但我现在走上了正确的轨道。
我可以确认我是否序列化数据库调用错误消失了。 我现在正在分析数据库,因为我的印象是在 ROW_LOCK 场景中我的数据写入不应该重叠另一方面有一个使用 MERGE 的 StoredProcedure 并且已知这是有问题的......
原来的问题就这样解决了,但是为什么try/catch没有捕获到一个简单的SqlException的问题确实入场了