为什么我的 ActionBlock 在没有设置的情况下会进入完成状态?

问题描述 投票:0回答:1

一时百思不得其解,想不出什么合理的解释。也许这里有人有解释。

设置: 我有一个生成大量工作项的类,需要使用

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;
        }

我的第一个猜测是被调用方法内部出现异常,但事实显然并非如此。

c# task-parallel-library tpl-dataflow
1个回答
0
投票

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

在 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的问题确实入场了

© www.soinside.com 2019 - 2024. All rights reserved.