У меня некрасивый кусок кода последовательного порта, который очень нестабилен.
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
while (port.BytesToRead > 0)
{
var count = port.BytesToRead;
byte[] buffer = new byte[count];
var read = port.Read(buffer, 0, count);
if (DataEncapsulator != null)
buffer = DataEncapsulator.UnWrap(buffer);
var response = dataCollector.Collect(buffer);
if (response != null)
{
this.OnDataReceived(response);
}
Thread.Sleep(100);
}
}
Если я удаляю вызовы Thread.Sleep (100), код перестает работать.
Конечно, это действительно тормозит, и если много потоков данных,
он тоже перестает работать, если я не заставлю спать еще больше.
(Перестает работать как в чистом тупике)
Обратите внимание, что DataEncapsulator и DataCollector являются компонентами
предоставлено MEF, но их производительность довольно хорошая.
В классе есть метод Listen (), который запускает фонового работника в
получить данные.
public void Listen(IDataCollector dataCollector)
{
this.dataCollector = dataCollector;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
port = new SerialPort();
//Event handlers
port.ReceivedBytesThreshold = 15;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
..... remainder of code ...
Предложения приветствуются!
Обновление:
* Просто краткая заметка о том, что делают классы IDataCollector.
Невозможно узнать, все ли байты данных были отправлены
читаются в одной операции чтения. Таким образом, каждый раз, когда данные читаются, это
передается в DataColllector, который возвращает true, когда завершено и
действительное сообщение протокола было получено. В данном случае это просто
проверяет байт синхронизации, длину, crc и хвостовой байт. Настоящая работа
делается позже другими классами.
*
Обновление 2:
Я заменил код сейчас, как предложено, но все же что-то не так:
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var count = port.BytesToRead;
byte[] buffer = new byte[count];
var read = port.Read(buffer, 0, count);
if (DataEncapsulator != null)
buffer = DataEncapsulator.UnWrap(buffer);
var response = dataCollector.Collect(buffer);
if (response != null)
{
this.OnDataReceived(response);
}
}
Вы видите, что это работает нормально с быстрым и стабильным соединением.
Но OnDataReceived НЕ вызывается при каждом получении данных.
(Подробнее смотрите в документах MSDN). Так что, если данные становятся фрагментированными
и вы читаете только один раз в случае потери данных.
И теперь я помню, почему у меня была петля во-первых, потому что
на самом деле он должен читать несколько раз, если соединение медленное или нестабильное.
Очевидно, я не могу вернуться к решению цикла while, что я могу сделать?