在Task.WhenAll中找到死锁

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

我发现下面的代码片段有死锁,虽然我已经通过使用读写锁解决了这个问题,但我仍然不知道在Task.WhenAll引起死锁的情况下究竟发生了什么。

有问题的代码:

   public async static Task<Dictionary<string, Log4SerialPort>> AvailableLog4SerialPorts()
        {
            var ports = App.SerialPortService.GetAvailablePorts();
            await Task.WhenAll(ports.Select(async port =>
            {
                if (!_availableLog4SerialPorts.ContainsKey(port.Path))
                {
                    var log4Port = new Log4SerialPort(port);
                    var isValid = await log4Port.Verify();
                    if (isValid)
                    {
                        _availableLog4SerialPorts.Add(port.Path, log4Port);
                    }

                }
            }));
            return _availableLog4SerialPorts;
        }

通过添加读写锁,问题解决了:

   public async static Task<Dictionary<string, Log4SerialPort>> AvailableLog4SerialPorts()
        {
            var ports = App.SerialPortService.GetAvailablePorts();
            await Task.WhenAll(ports.Select(async port =>
            {
                rwl.AcquireReaderLock(VERIFY_TIMEOUT);
                if (!_availableLog4SerialPorts.ContainsKey(port.Path))
                {
                    rwl.ReleaseReaderLock();
                    var log4Port = new Log4SerialPort(port);
                    var isValid = await log4Port.Verify();
                    if (isValid)
                    {
                        rwl.AcquireWriterLock(VERIFY_TIMEOUT);
                        _availableLog4SerialPorts.Add(port.Path, log4Port);
                        rwl.ReleaseWriterLock();
                    }

                }
            }));
            return _availableLog4SerialPorts;
        }

_availableLog4SerialPorts是一个静态领域。

log4Port.Verify()不共享任何静态资源,它只是做一些耗时的任务。

似乎Task.WhenAll会自动锁定静态资源,但不确定它是如何工作的,以及在这种情况下的详细阻塞原因。

c# multithreading xamarin task deadlock
1个回答
1
投票

我制作了一个小程序来重现这个问题,似乎程序被阻止的原因与@Michael Randall所说的一样,Dictionary在多线程环境中可能会导致意外行为。以下是测试的屏幕截图。没有锁,程序将在执行期间的任意点阻塞。

without locks

with locks(对不起,我还是无法嵌入图片......)

感谢您的所有帮助:)

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