C#
.NET
UWP
シリアル通信

[UWP] SerialDeviceのDisposeが終了しない場合の回避策

概要

Raspberry Pi 3 + Windows IoT + UWPの環境において、SerialDeviceのDispose()が終了しない問題が発生した。
この回避策を述べる。

発生した環境

  • Raspberry Pi 3 Model B
  • Windows 10 IoT
  • Microsoft.NETCore.UniversalWindowsPlatform 6.0.6 & 6.1.5
  • USB-UART変換ケーブル

現象

Raspberry Pi 3 + Windows IoT + UWPの環境において、以下のコードを定期的に実行しながら、そのUART0に向けてシリアル通信で外部から送信を続けると、時折、serialDevice.Dispose()が終了しないということが発生する。

hang.cs
var serialDevice = await SerialDevice.FromIdAsync(id);
serialDevice.BaudRate = ...
serialDevice.DataBits = ...
serialDevice.Parity = ...
serialDevice.StopBits = ...
serialDevice.Handshake = ...

var dataWriter = new DataWriter(serialDevice.OutputStream);
var dataReader = new DataReader(serialDevice.InputStream);

uint size = await dataReader.LoadAsync(256);
if (size > 0)
{
    var buffer = new byte[size];
    dataReader.ReadBytes(buffer);
}

System.Diagnostics.Debug.WriteLine("Disposing");
serialDevice.Dispose();
dataWriter.Dispose();
dataReader.Dispose();
System.Diagnostics.Debug.WriteLine("Disposed");

また、Dispose()の順序をDataWrtier/DataReaderを先にした場合、先にDisposeした部分で同様の問題が発生する。

解決策

Dispose前で100ms待機する。

await Task.Delay(100);

serialDevice.Dispose();
dataWriter.Dispose();
dataReader.Dispose();

これを追加して以来、Disposeが終了しない問題は起きていない。
なぜこれで解決するのかはわからない。興味がある人は下記リンクにあたってほしい。
ひとつめのリンクが100ms待機するという対応を教えてくれたソースであり、その情報が根拠としているのがふたつめのリンク(こちらはUWPではない.NET環境のSerialPortクラスの情報)になっている。

参考にした情報

Windows IoT BackgroundTask Async/Await
https://stackoverflow.com/questions/44893263/windows-iot-backgroundtask-async-await

Why Thread.Sleep() before SerialPort.Open and Close?
https://stackoverflow.com/questions/6434297/why-thread-sleep-before-serialport-open-and-close/14313505