如何从定时事件恢复功能
本文关键字:恢复 功能 事件 定时 | 更新日期: 2023-09-27 18:21:58
好吧,我有一个名为readSensor的函数,你猜到了…读取传感器。
但传感器通常需要大约100毫秒才能做出响应。所以在readSensor功能中,我基本上只是启动了一个计时器。
在定时事件中,我读取串行端口并得到响应。
然而,这意味着当我希望响应在readSensor函数中时,它在onTimedEvent中。。
基本上,从主要形式来看,我希望能够做到这一点。
value=读取传感器()
此时,我所能做的就是读取Sensor(),然后在timedEvent触发后,我可以通过在消息框中显示它来看到响应正在返回。
这是我的密码。(我错过了大量的串行端口设置和其他东西,但希望你能看到我的问题)
我不想只在函数中等待100毫秒,尽管轮询计时器,因为这会使我的程序变慢。。
我想以某种方式将响应返回到readSensor功能,然后返回到表单。
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Timers;
namespace readSensor
{
public partial class readSens : UserControl
{
public readSens()
{
InitializeComponent();
}
private System.Timers.Timer rTimer;
SerialPort sp = new SerialPort();
private void setupTimer()
{
// Create a timer with a 100ms response.
rTimer = new System.Timers.Timer(100);
rTimer.SynchronizingObject = this;
// Hook up the Elapsed event for the timer.
rTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
}
public string getResponse()
{
string status = "";
byte[] readBuffer = new byte[255];
if (sp.IsOpen)
{
if (sp.BytesToRead > 0) //there is data to read
{
int length = sp.BytesToRead;
for (int i = 0; i < length; i++)
{
readBuffer[i] = (byte)sp.ReadByte();
status = "pass";
return status;
}
}
}
public void readSensor(byte addr)
{
if (!sp.IsOpen)
{
openPort();
readSensor(addr); // calls itself again once port is opened
}
else if (sp.IsOpen)
{
rTimer.Start();
}
else
{
MessageBox.Show("Port not opened yet");
}
}
}
}
在主要形式中,我基本上只是说
setupTimer();
readSensor();
点击按钮。
我认为如果没有一些回调机制,你无法做到这一点。您可以实现while循环,但这并不有效,因为它会引入旋转。
我的建议是实现一个合适的异步模式或一些简单的东西,比如:
ReadSensor(addr, DoSomethingWithResult);
public void DoSomethingWithResult(string result)
{
Console.WriteLine (result);
}
public partial class ReadSens : UserControl
{
private Action<string> _responseCallback;
public void ReadSensor(byte addr, Action<string> responseCallback)
{
_responseCallback = responseCallback;
// initiate timer
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
_responseCallback(response);
}
}
启动一个单独的线程,然后从该线程将结果写入队列,并返回到主线程中。
class Game1
{
//We declare a queue, which is like an array that we can extract and enter data easily in a FIFO (first in, first out) style list.
Queue<string> q = new Queue<string>();
public void threadStart(object obj)
{
//We get the result of your function, while our main function is still looping and waiting.
string result = readInput()
//We tell C# that the parameter we passed in, is in fact the Game1 class passed from "t.Start"
Game1 game = (Game1)obj;
//This puts our "result" into the queue.
game.q.Enqueue(result);
}
public void start()
{
//Declares a new thread, which will run "threadStart" function.
System.Threading.Thread t = new System.Threading.Thread(threadStart);
//We start the other thread (that will run in parallel) and pass "this" as the parameter.
t.Start(this);
//We loop over and over, sleeping, whilst the other function runs at the same time. This is called "multi- threading"
while (q.Count == 0)
{
System.Threading.Thread.Sleep(10);
}
//This gets the last-entered (oldest) value from the queue q.
string result = q.Deque();
}
}
因此,这会启动一个线程来获取结果,然后在我的版本中,轮询队列一段时间,直到结果出来,但在你的版本中可以做很多事情,只要你不时地检查队列中的新数据。
编辑:添加了评论,希望能缓解你的一些问题。
这种方法对您来说是有效的解决方案吗?我认为您只是在使用Timer
来等待serialPort打开,但它可以通过引发事件进行自我控制。
public class SensorReader
{
private Sensor sensor;
private string lastResponse;
public SensorReader(SerialPort serialPort)
{
this.serialPort = aSerialPort.
this.sensor = new Sensor(serialPort);
this.sensor.PortOpen += PortOpenEventHandler(OnPortOpen);
}
private void OnPortOpen()
{
this.ReadPort();
}
public string ReadPort(byte address)
{
if (!this.sensor.IsOpen)
{
this.sensor.OpenPort();
this.lastResponse = "The serial port doesn't respond... yet!";
}
else
{
// Read response at this point.
this.lastResponse = this.GetResponse();
}
return this.lastResponse;
}
}
public class Sensor
{
private SerialPort serialPort;
public Sensor(SerialPort aSerialPort)
{
this.serialPort = aSerialPort;
}
public bool IsOpen
{
get { return this.serialPort.IsOpen; }
}
public delegate void PortOpenEventHandler(object sender, EventArgs e);
public event PortOpenEventHandler PortOpen;
public void OpenPort()
{
// Open port here...
// ... and throw the PortOpen event.
if (this.PortOpen != null)
{
this.PortOpen(this, EventArgs.Empty);
}
}
}