Цель - создать службу в windows которая считывает данные из COM порта обрабатывает и в данном случае будет писать в текстовый файл. Собственно проблема в следующем, не могу получить данные из SerialPort знаю точно что порт открыт,знаю точно что порт отправляет данные. При попытке прочитать строку ReadLine() не получает ничего.
Как решить эту проблему?
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
this.CanStop = true;
this.CanPauseAndContinue = true;
this.AutoLog = true;
}
comWatcher cWatch;
protected override void OnStart(string[] args)
{
cWatch = new comWatcher();
Thread watcher = new Thread(new ThreadStart(cWatch.Start));
watcher.Start();
}
protected override void OnStop()
{
cWatch.Stop();
Thread.Sleep(1000);
}
}
class comWatcher
{
SerialPort port;
bool enabled = true;
public comWatcher()
{
Log("start");
this.port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
this.port.DataReceived += port_DataReceived;
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Log(port.ReadLine());
}
public void Start()
{
try
{
this.port.Open();
}
catch (IOException io)
{
Log(io.Message);
}
while (enabled)
{
Thread.Sleep(1000);
}
}
public void Stop()
{
port.Close();
enabled = false;
}
public void Log(string message)
{
File.AppendAllText(@"C:\\log.txt", message);
}
}
Вы делаете неправильно.
Приход сообщения DataReceived
означает лишь, что в порту появились данные, но не означает, что их набралось на целую строку. То, что в порт данные записываются построчно, вовсе не даёт гарантии, что они будут и приходить построчно тоже.
Если вы хотите вычитать все имеющиеся данные, имеет смысл использовать port.ReadExisting()
вместо ReadLine
.
Но более хорошей альтернативой мне кажется получение у порта BaseStream
и работа с ним, как с потоком (не со строками, а с байтами):
class ComWatcher
{
SerialPort port;
bool enabled = true;
CancellationTokenSource cts;
public ComWatcher()
{
this.port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
}
public async void Start()
{
if (cts != null)
throw new InvalidOperationException("Already started");
cts = new CancellationTokenSource();
var ct = cts.Token;
try
{
port.Open();
byte[] buf = new byte[256];
var stream = port.BaseStream;
using (var outf = File.OpenWrite(@"C:\\log.txt"))
while (!ct.IsCancellationRequested)
{
var actuallyRead = await stream.ReadAsync(buf, 0, buf.Length, ct);
if (actuallyRead == 0) // end of stream
return;
await outf.WriteAsync(buf, 0, actuallyRead);
}
}
catch (IOException io)
{
if (!ct.IsCancellationRequested)
LogError(io.Message);
}
}
public void Stop()
{
var cts = this.cts;
this.cts = null;
if (cts == null)
throw new InvalidOperationException("Not started");
port.Close();
cts.Cancel();
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Имеется (c# wpf) окно, в котором динамически показываются разные контролы (фреймы)Набор показываемых контролов определяется в главной vm
Я понимаю общие принципы Master/Slave, но как это красиво наложить на WCF очень туманно вижу
Задача: слияние узлов XML и классов, где свойства помеченные атрибутом ToXmlAttribute, являются атрибутами Xml (Node Name=""):