У меня есть многопоточное приложение на C#, которое должно взаимодействовать с аппаратным обеспечением с помощью SerialPort.serialport многопоточное незапрашиваемое сообщение
Программа представляет собой в основном последовательность ответа команд, но аппаратное обеспечение может отправлять незапрашиваемое сообщение «СБРОС» из-за внутренней ошибки, в течение которой программное обеспечение должно повторно инициализировать его, отправив последовательность команд, устанавливающих определенные значения.
Более один поток (от ThreadPool) можно попробовать сделать TakeSampleNow()
public class ALComm
{
private readonly AutoLoaderManager _manager;
private readonly AutoResetEvent dataArrived = new AutoResetEvent(false);
private SerialPort _alPort;
private string _alResponse;
.... Code to init _alPort and attach datareceived event etc
public void TakeSampleNow()
{
if (Monitor.TryEnter(_alPort, 1000)) //let's wait a second
{
_manager.MessageList.Enqueue("Try sampling");
try
{
Send("Command1");
string response = Receive();
switch(response)
{
case "X": blah blah..
case "Y": blah blah..
}
Send("Command2");
string response = Receive();
while(response != "OK")
{
Send("Command3");
string response = Receive();
Send("Command2");
string response = Receive();
}
}
finally
{
Console.WriteLine("Releasing port");
//Thread.CurrentThread.Priority = ThreadPriority.Normal;
Monitor.Exit(_alPort);
}
else
{
_manager.MessageList.Enqueue("Port is busy!!!");
}
}
public string Receive()
{
string inString = null;
dataArrived.WaitOne(1000);
inString = _alResponse;
return inString;
}
private void AlPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
_alResponse = _alPort.ReadLine();
//if (_alResponse.ToUpper().Contains("RESET"))
//{
// _alState = AlState.Reset;
// TryInitialize();
//}
dataArrived.Set();
}
private void TryInitialize()
{
Monitor.Enter(_alPort); //lock so other threads do not access samplenow during initialization
try
{
string response;
Console.WriteLine("Initializing ... The AutoLoader");
_alPort.DiscardInBuffer();
Send("CommandX");
response = Receive();
--- blah blah
_alResponse = "";
}
finally
{
Monitor.Exit(_alPort);
}
}
я могу проверить реакцию в DataReceived события и ждать на замке в TryInitialize() и для других потоков в TakeSampleNow чтобы освободить блокировку, мне пришлось бы проверять каждый ответ, если _alResponse содержит «RESET», и если он возвращается из метода. Это делает его более запутанным.
Любые предложения о том, как я могу сделать это лучше. Я считаю, что это может быть машина состояний, но я не могу ее концептуализировать.
Незапрошенные ответы - большая проблема. Особенно, когда он говорит «СБРОС», это ответ «Я упал и не могу встать». Вам нужно стремиться к тому, чтобы * никогда не получить такой ответ. Или перезагрузите компьютер, когда вы его получите, потому что это то, что сделал устройство. –
Я бы тоже хотел перезапустить службу .. но это служба Windows, которая контролируется пользователем через браузер. – cheedep