C# 使用计时器轮询硬件的事件处理

C# 使用计时器轮询硬件的事件处理,c#,delegates,timer,event-handling,C#,Delegates,Timer,Event Handling,我需要使用特定硬件(气象站)制造商提供的DLL中的函数来请求值。我是C#的新手,代表/事件的概念很难让我理解。尽管如此,我还是设法从DLL中提取了函数,并验证了数据是否能够通过。我的问题是使用计时器定期轮询仪器。在Initialize()中,实例化了一个对象,但不处理该事件,将对象保留为null。我没有主意了,想听听你的建议 public class HardwareData : EventArgs { public float OutsideTemp { get; set; }

我需要使用特定硬件(气象站)制造商提供的DLL中的函数来请求值。我是C#的新手,代表/事件的概念很难让我理解。尽管如此,我还是设法从DLL中提取了函数,并验证了数据是否能够通过。我的问题是使用计时器定期轮询仪器。在
Initialize()
中,实例化了一个对象,但不处理该事件,将对象保留为null。我没有主意了,想听听你的建议

public class HardwareData : EventArgs
{
    public float OutsideTemp { get; set; }
    public int OutsideHum { get; set; }
    public float WindSpeed { get; set; }
    public int WindDirection { get; set; }
}

public class Hardware : IDisposable
{
    private static Hardware v;
    private System.Timers.Timer hardwareTimer;
    private int counter = 0;
    private static readonly object padlock = new object();
    public static Hardware Instance
    {
        get
        {
            lock (padlock)
            {
                if (v == null)
                    v = new Hardware();
                return v;
            }
        }
    }

    public void Initialize()
    {
        try
        {
            hardwareTimer = new System.Timers.Timer(500);
            hardwareTimer.Elapsed += new ElapsedEventHandler(hardwareTimer_Elapsed);
            HardwareVue.OpenCommPort_V(3, 19200); //COM port and baud rate are verified.
            hardwareTimer.Start();
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("Unable to initialize.", ex);
        }
    }

    public HardwareData LastHardware { get; set; }

    void hardwareTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            counter += 1;
            Console.WriteLine(counter);
            HardwareVue.LoadCurrentHardwareData_V();
            HardwareData v = new HardwareData()
            {
                OutsideTemp = HardwareVue.GetOutsideTemp_V(),
                OutsideHum = HardwareVue.GetOutsideHumidity_V(),
                WindSpeed = HardwareVue.GetWindSpeed_V(),
                WindDirection = HardwareVue.GetWindDir_V()
            };
            LastHardware = v;
        }
        catch (Exception) { }
    }

    public void Dispose()
    {
        HardwareVue.CloseCommPort_V();
        hardwareTimer.Stop();
    }
}


[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Hardware test = new Hardware();
        try
        {
            if (test != null)
            {
                test.Initialize();
                test.Dispose();
                Assert.AreEqual(0, test.LastHardware.OutsideHum);
            }
        }
        catch (NullReferenceException ex)
        {
            Console.WriteLine("Object is null.");
        }
        // Console.WriteLine(test.LastHardware.OutsideHum);

    }
}

使用计时器时,您需要启用计时器并确保事件已初始化:

hardwareTimer.Enabled = true;
hardwareTimer.CanRaiseEvents = true;
供参考:

编辑
除了对OP的问题和此答案的其他注释外,LastHardware为null的问题是由于在计时器最初启动之前从未实例化该属性。要解决此问题,您应该在默认构造函数(或
Initialize
方法)中实例化LastHardware属性:


当然,您希望在实例化时设置一些默认值。

初始化测试,然后立即处理它(终止计时器)。True。在我看来,计时器将经过一个间隔,加载数据,然后被处理。不,你需要暂停线程以等待计时器启动。尝试在初始化和处置之间添加类似Thread.Sleep(2000)的内容。我的意思是只为测试而这样做,在实际的应用程序中,只需继续您的业务并做其他事情。或者,您可以将硬件类之外的计时器带到测试类中,并在test.PollHardware()调用后,在TimeRecursed处理程序的末尾调用dispose方法,或者您想调用的任何方法。您只需将“test”作为计时器访问它的全局引用即可。啊哈!非常感谢。我现在可以测试并查看正在传输的数据,并且默认情况下timer incrementing.CanRaiseEvents为true,timer.Start()与timer.Enabled=true相同。我想说,真正的问题是,正如Alex指出的,他在初始化后立即处理,因此没有足够的时间来做任何事情。这就是我的绝对困惑:在测试类中,如果我要声明一个计数器,用于每间隔递增,我不知道在循环中包装什么,这样我就可以测试多个计时器间隔。for(int I=0;I<5;I++){timer mytimer=new timer(100*I);mytimer.appeased+=new ElapsedEventHandler(mytimer_appeased);}void mytimer_appeased(对象发送方,ElapsedEventArgs e){int I=((timer)发送方).Interval/100;Console.WriteLine(“计时器编号”+i.toString()+“已用”);}
public Hardware()
{
  LastHardware = new HardwareData();
}