【发布时间】:2019-02-18 01:35:39
【问题描述】:
我发现下面的代码sn-p有死锁,虽然我已经通过读写锁解决了这个问题,但我仍然不知道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会自动锁定静态资源,但不确定它是如何工作的,以及这种情况下的详细阻塞原因。
【问题讨论】:
-
如果结构不是线程安全的,那么在多线程环境中使用它们会产生意想不到的后果......如果不知道您正在使用的每个结构的工作原理,那么我们几乎不可能猜猜是什么导致了问题,但很高兴你解决了它。但请注意,
Dictionary不是线程安全的,谁知道Log4SerialPort做了什么 -
您可能必须从
AvailableLog4SerialPorts开始上链。你怎么称呼它? -
你说,我发现下面的代码sn-p有死锁。你怎么知道的?
-
@CodingYoshi @John @MichaelRandall
Log4SerialPort就像System.IO.Ports.SerialPort的包装,而AvailableLog4SerialPorts是静态Dictionary<string, Log4SerialPort>。我认为这是一个死锁,因为在我手动添加读写锁后,问题就解决了。而且我还在阅读其他已发布的问题,似乎是多线程中的字典
标签: c# multithreading xamarin task deadlock