我有一个协议ID
p_id
,可以检查当前正在读取哪个设备。以下是我的代码:下面是我的主函数,调用了一个名为
CombinedEngine
的类。 static class Program
{
private static CombinedEngine _eng;
static async Task Main(string[] args)
{
try
{
_eng = new CombinedEngine();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message.ToString());
//_log.Error(ex, ex.Message);
}
}
while(true);
}
合并引擎类
class CombinedEngine
{
SerialPort port = new SerialPort();
public CombinedEngine()
{
try
{
var p = mdc.mdc_protocol.ToList();
if(p.Count > 0)
{
foreach(var pr in p)
{
var p_id = pr.protocol_id;
if(p_id=="01")//modbus
{
if (port.IsOpen)
port.Close();
port = new SerialPort("COM8", 9600, Parity.Even, 8, StopBits.One);
port.ReadTimeout = 500;
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
port.Open();
Console.WriteLine("Port opened successfully for modbus...");
Console.WriteLine("I am Recieving for modbus...");
var result = mdc.mdc_meter_config.Where(m => m.config_flag == 0)
.Where(m=>m.p_id == p_id).ToList();
if (result.Count > 0)
{
foreach (var item in result)
{
var iteration = new Iterations()
{
hex = (string)item.m_hex,
row_id = (string)item.row_id,
device_id = (int)item.meter_id,
protocol_id = (string)item.p_id,
command_id = (string)item.command_id,
config_flag = (int)item.config_flag,
msn = (string)item.msn,
time = (string)item.time
};
confList.Add(iteration);
time = Convert.ToDouble(item.time);
}
var modbus = confList.Where(x => x.protocol_id == "01").ToList();
aTimer = new System.Timers.Timer();
// Create a timer...
aTimer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer.
aTimer.Interval = time * 1000.0;
aTimer.Elapsed += (sender, e) => MyModbusMethod(sender, e, modbus, aTimer);
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
else
{
Console.WriteLine("No Data available");
}
}
else if(p_id=="02")//ytl_bus
{
if (port.IsOpen)
port.Close();
port = new SerialPort("COM8", 38400, Parity.None, 8, StopBits.One);
port.ReadTimeout = 500;
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
port.Open();
Console.WriteLine("Port opened successfully for ytlbus...");
Console.WriteLine("I am Recieving for ytlbus...");
var result = mdc.mdc_meter_config.Where(m => m.config_flag == 0)
.Where(m => m.p_id == p_id).ToList();
if (result.Count > 0)
{
foreach (var item in result)
{
var iteration = new Iterations()
{
hex = (string)item.m_hex,
row_id = (string)item.row_id,
device_id = (int)item.meter_id,
protocol_id = (string)item.p_id,
command_id = (string)item.command_id,
config_flag = (int)item.config_flag,
msn = (string)item.msn,
time = (string)item.time
};
confList.Add(iteration);
time = Convert.ToDouble(item.time);
}
var ytlbus = confList.Where(x => x.protocol_id == "02").ToList();
aTimer = new System.Timers.Timer();
// Create a timer...
aTimer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer.
aTimer.Interval = time * 1000.0;
aTimer.Elapsed += (sender, e) => MyElapsedMethod(sender, e,ytlbus , aTimer);
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
else
{
Console.WriteLine("No Data available");
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error at Line " + LineNumber(), ex.Message.ToString());
throw ex;
}
}
}
在上述代码中,我已经检查了如果
p_id
等于01
,那么应该进行modbus
串口配置。但是,如果p_id
是02
,则应遇到ytlbus
串口配置。这两个设备具有不同的波特率和奇偶校验位。因此,我尝试对它们进行设置。另外,我有一个计时器,它是
60
秒。因此,在每个60
秒后,下一个计时器将被初始化。例如,如果
p_id
是01
,则代码将设置波特率为9600
,并将奇偶校验位设置为Even
。然后调用SerialDataRecievedEventHandler
,它将检查设备是否有任何传入数据,并负责将数据转储到DB
中。然后,代码将从表格
mdc_meter_config
中检查设备详细信息,并从中提取相关信息。对于所有设备,所有细节都逐一添加到列表中。同时,时间也会被记录。在这种情况下,所有设备的时间都是相同的,即60秒。然后,将该列表传递给一个变量,然后将其传递给
ElapsedEventHandler
函数。它处理frame
发送。对于
p_id
等于02
,将执行相同的操作,唯一的区别是将波特率设置为38400
,奇偶校验设置为None
。我面临的问题是以上代码运行时,我遇到的问题是两个条件同时起作用。即对于
01
,它将起作用,然后同时跳转到02
条件。下面是图片。
它应该完成任何p_id
值的工作,然后完成其他p_id
值的工作。
更新1
我已经更新了我的代码。添加了一个新的async
函数,仅添加了一个计时器,并为串口扩展添加了一个类。 public static class SerialPortExtensions
{
public async static Task ReadAsync(this SerialPort serialPort, byte[] buffer, int offset, int count)
{
var bytesToRead = count;
var temp = new byte[count];
while (bytesToRead > 0)
{
var readBytes = await serialPort.BaseStream.ReadAsync(temp, 0, bytesToRead);
Array.Copy(temp, 0, buffer, offset + count - bytesToRead, readBytes);
bytesToRead -= readBytes;
}
}
public async static Task<byte[]> ReadAsync(this SerialPort serialPort, int count)
{
var buffer = new byte[count];
await serialPort.ReadAsync(buffer, 0, count);
return buffer;
}
}
public CombinedEngine()
{
try
{
var p = mdc.mdc_protocol.ToList();
if (p.Count > 0)
{
foreach (var pr in p)
{
var p_id = pr.protocol_id;
if (p_id == "01")//modbus
{
if (port.IsOpen)
port.Close();
comm = true;
port = new SerialPort("COM8", 9600, Parity.Even, 8, StopBits.One);
port.ReadTimeout = 500;
//port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
port.Open();
Work();
Console.WriteLine("Port opened successfully for modbus...");
Console.WriteLine("I am Recieving for modbus...");
}
else if (p_id == "02")//ytl_bus
{
if (port.IsOpen)
port.Close();
comm = true;
port = new SerialPort("COM8", 38400, Parity.None, 8, StopBits.One);
port.ReadTimeout = 500;
//port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
port.Open();
Work();
Console.WriteLine("Port opened successfully for ytlbus...");
Console.WriteLine("I am Recieving for ytlbus...");
}
var result = mdc.mdc_meter_config.Where(m => m.config_flag == 0).ToList();
if (result.Count > 0)
{
foreach (var item in result)
{
var iteration = new Iterations()
{
hex = (string)item.m_hex,
row_id = (string)item.row_id,
device_id = (int)item.meter_id,
protocol_id = (string)item.p_id,
command_id = (string)item.command_id,
config_flag = (int)item.config_flag,
msn = (string)item.msn,
time = (string)item.time
};
confList.Add(iteration);
time = Convert.ToDouble(item.time);
}
var modbus = confList.Where(x => x.protocol_id == "01").ToList();
var ytlbus = confList.Where(x => x.protocol_id == "02").ToList();
//ModbusMethod(modbus);
aTimer = new System.Timers.Timer();
// Create a timer...
aTimer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer.
aTimer.Interval = time * 1000.0;
aTimer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, ytlbus, modbus, aTimer);
//aTimer.Elapsed += OnTimedEvent(iterations, dataItems);
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
else
{
//Console.WriteLine("No Data available");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error at Line " + LineNumber(), ex.Message.ToString());
throw ex;
}
finally
{
}
}
public async void Work()
{
try
{
var data = await port.ReadAsync(4096);
Console.WriteLine("Data at Line " + LineNumber(), data.ToString());
//DoStuff(data);
}
catch (Exception ex)
{
Console.WriteLine("Error at Line " + LineNumber(), ex.Message.ToString());
}
}
我现在遇到的错误是
由于线程退出或应用程序请求,I/O 操作已中止。
错误发生在下面的行。在System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)处发生错误 在System.IO.Ports.SerialStream.EndRead(IAsyncResult asyncResult)处终止读取操作 在System.IO.Stream.<>c.b__43_1(Stream stream, IAsyncResult asyncResult)处 在System.Threading.Tasks.TaskFactory<code>1.FromAsyncTrimPromise</code>1.Complete(TInstance thisRef, Func<code>3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)处 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)处抛出非成功的任务 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)处处理非成功和调试器通知的任务 在CommunicationProfile.SerialPortExtensions.d__0.MoveNext()处,位于F:\MDC Development\Scheduler\CommunicationProfile\CombinedEngine.cs第1198行 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)处抛出非成功的任务 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)处处理非成功和调试器通知的任务 在System.Runtime.CompilerServices.TaskAwaiter.GetResult()处获取结果 在CommunicationProfile.SerialPortExtensions.d__1.MoveNext()处,位于F:\MDC Development\Scheduler\CommunicationProfile\CombinedEngine.cs第1207行 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)处抛出非成功的任务 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)处处理非成功和调试器通知的任务 在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()处获取结果 在CommunicationProfile.CombinedEngine.d__27.MoveNext()处,位于F:\MDC Development\Scheduler\CommunicationProfile\CombinedEngine.cs第368行
var readBytes = await serialPort.BaseStream.ReadAsync(temp, 0, bytesToRead);//1198 line
await serialPort.ReadAsync(buffer, 0, count);//1207 line
var data = await port.ReadAsync(4096); // 368 line
注意:上述方法应在设备通电后持续运行,并在每个60
秒后发送其数据。
非常感谢您的帮助。
while(true);
... 烤一下CPU。尝试使用Console.ReadLine();
代替。 - Fildor