Я обнаружил, что приведенный ниже фрагмент кода имеет тупиковую ситуацию, хотя я уже решил эту проблему с помощью блокировки чтения и записи, но до сих пор не представляю, что именно происходит под защитой в Task.When, что вызывает тупик.
Проблематичнокод:
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 автоматически заблокирует статические ресурсы, но не уверен, как это работает, и подробные причины блокировки в этом случае.