Пишу прогу, .Net c# WPF, принимает и обрабатывает данные по COM порту. Используется SerialPorts из System.IO.Ports.dll
Красным полупрозрачным маркером на скринах выделено то, что по моему не влияет на ошибку. Элементы wpf и другая "косметика"
Метод CloseSerial сначала переключает int portState в 0, потом закрывает порт с помощью SerialP.Close()
portState используется при для переключения открыт/закрыт порта и как bool для while внутри асинхронных методов: метод чтения GetData() и метод отправки SendData запускается сразу после открытия порта методом OpenSerial()
Если убрать GetData, то все работает нормально. Порт открывается и закрывается, при этом делая это по настоящему, данные отправляются.
Но вот при добавлении GetData при попытке закрыть порт возникает
Вызвано исключение: "System.OperationCanceledException" в System.IO.Ports.dll
Вылазит на строке RawData = SerialP.ReadLine(); То есть на чтении
При этом, судя по выводу, SerialP.Close() отрабатывает нормально и внутри GetData(); Условие if (SerialP.IsOpen == true | portState == 1) возвращает false, соотв RawData = SerialP.ReadLine(); вообще не должна выполняться. Но исключение вылазит именно на ней, VisualStudio на нее показывает по крайней мере
Кстати, если закомментировать строку RawData = SerialP.ReadLine(); исключение не возникает. И закрытие/открытие порта отрабатывает штатно
Приложение крашит, обработать исключение у меня не получилось. Инфы в инете тоже нету, только решенные вопросы по Azure, но там не мой случай. На learn.microsoft ничего толком не понял, как то слишком профессионально у них написано
Что сделал:
Ставил задержки. На случай если порт закрывается не моментально
Пробовал читать посимвольно. Результат тот же.
Пробовал много разных проверок и (опять же) обработки исключения
Подскажите пожалуйста что делаю не так
Код:
*Я вырезал из кода всякие назначения цветов для кнопок wpf, что бы не превысить колво символов
void OpenSerial()
{
try
{
SerialP.PortName = TBX_SerialPortName.Text;
SerialP.BaudRate = 115200;
SerialP.StopBits = StopBits.One;
SerialP.Parity = Parity.None;
SerialP.Open();
}
catch
{
Trace.WriteLine("Исключение. Не удается открыть порт");
}
finally
{
if(SerialP.IsOpen == true)
{
portState = 1;
SendData();
GetData();
}
}
}
void CloseSerial()
{
Trace.WriteLine("CloseSerial");
try
{
cancelTokenSource.Cancel();
portState = 0;
Thread.Sleep(3000);
Trace.WriteLine("Next hop SerialP.Close()");
SerialP.Close();
Thread.Sleep(3000);
}
catch
{
Trace.WriteLine("Не удается закрыть порт");
}
finally
{
if (SerialP.IsOpen == false)
{
Trace.WriteLine("IsOpen=false");
}
}
}
public async void GetData()
{
CancellationToken token = cancelTokenSource.Token;
await Task.Run(() =>
{
while (portState == 1)
{
if (token.IsCancellationRequested)
{
Trace.WriteLine("Операция прервана");
return;
}
if (SerialP.IsOpen == true | portState == 1)
{
Trace.WriteLine("выа");
NowKey = "";
Trace.WriteLine("р");
try
{
RawData = SerialP.ReadLine();
}
catch (TimeoutException) { }
Trace.WriteLine("OPEN");
if (RawData != null & RawData != "")
{
NowKey = RawData.Substring(0, 2);
Data = RawData.Substring(2);
}
Thread.Sleep(100);
}
}
},token);
}
Полный код без изменений:
https://ideone.com/P8ByKW
Не разобрался как поделится кодом в jsfiddle