在Task.WhenAll中发现死锁

时间:2019-02-18 01:35:39

标签: c# multithreading xamarin task deadlock

我发现下面的代码段具有死锁,尽管我已经通过使用读写锁解决了这个问题,但我仍然不知道Task.WhenAll到底会导致死锁的确切情况是什么。

问题代码:

%*d

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

   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不共享任何静态资源,它仅执行一些耗时的任务。

似乎Task.WhenAll会自动锁定静态资源,但不确定这种情况下的工作方式以及详细的阻止原因。

1 个答案:

答案 0 :(得分:1)

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

without locks

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

感谢您的所有帮助:)