将变量传递给类中的定时事件 [英] Passing variables to a timed event in a class

查看:59
本文介绍了将变量传递给类中的定时事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在类中有一个方法,它从/向Form1接收并返回多个参数。我需要使用定时事件来使用这些参数执行一些代码。我已经安排了这个简化的代码来显示动态:



I have a method in a class that receives and returns multiple parameters from/to Form1. I need to use a timed event to execute some code using those parameters. I have arranged this simplified code to show the dynamic:

class Motor
{
    public static System.Timers.Timer _timer;
    int valReg = 30;

    public void PID(decimal _actualSpeed, Decimal _speedRequest, out Decimal _pwmAuto, out decimal _preValReg)
    {

        _timer = new System.Timers.Timer();
        _timer.Interval = (3000);
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timerAutoset);
        _timer.Enabled = true;
        // {....}
        _pwmAuto = valReg;
        _preValReg = valReg - 1;
    }
    static void _timerAutoset(object sender, System.Timers.ElapsedEventArgs e)
    {
        /* here I need to work with:
         _actualSpeed
         _speedRequest
         _pwmAuto
         _preValReg
        and send back the last two variables
         */
    }    
}



这是我从Form1按钮传递和接收变量的方式:




This is how I pass and receive the variables from Form1 button :

private void button4_Click(object sender, EventArgs e)
       {
       // some code ................
       Motor mtr = new Motor();
       mtr.PID(speedRequest, actualSpeed, out pwmAuto, out xxx);
       //..more code



如何将这些参数传递给_timerAutoset事件/从_timerAutoset事件返回?


How can I pass/get back those parameters to/from _timerAutoset event?

推荐答案

两种方式:

Two ways:
  1. 您的 Elapsed 事件处理程序方法可能是实例一(非静态)。在这种形式中,它将通过this参数访问其声明类的整个实例(如果没有歧义,可以省略关键字this)。

  2. 使处理程序成为匿名方法。它允许您使用闭包功能。闭包将使本地变量在方法的生命周期之外可访问,并在计时器的事件调用列表中添加处理程序。请参阅:

    http://en.wikipedia.org/wiki/Closure_%28computer_science %29 [ ^ ]。< br $> b $ b

    警告!只有在您清楚了解它是如何工作的时候才小心使用。
  1. Your Elapsed event handler method could be instance one (non-static). In this form, it will get access to the whole instance of its declaring class, via "this" parameter (keyword "this" could be omitted if there is no an ambiguity).
  2. Make a handler an anonymous method. It will allow you to use the closure feature. The closure will make even the local variable accessible beyond the lifetime of the method adding a handler to the timer''s event invocation list. Please see:
    http://en.wikipedia.org/wiki/Closure_%28computer_science%29[^].

    Warning! Use with care, only when you understand well how it works.





是否足够或您需要更多细节?如果您需要,请回复。







我可以看到,它仍然需要一些插图。首先是实例处理程序:





Is it enough or do you need more detail? Please respond if you need them.



As I can see, it still need some illustrations. First and foremost, instance handler:

class Motor {

    System.Timers.Timer timer = new System.Timers.Timer();
    int valReg = 30;

    void timerHandler(object sender, System.Timers.ElapsedEventArgs e) {
        // ...
        this.valReg++; // as this method is an instance method,
                       // you can access it via the instance
        //...
        // same as
        valReg++; // this is needed just for understanging
                  // or if you need to resolve some ambiguity
    } //timerHandler

    void SomeTimerSettingMethod() { // could also be a constructor
        timer.Elapsed += timerHandler; // the new "System.Timers.ElapsedEventHandler"
                                       // ceremony is not really needed
        // ...
    } // SomeTimerSettingMethod

    //...

} // Motor





现在,关闭的方法。它更精致:



Now, the approach with closure. It''s more delicate:

class Motor {

    System.Timers.Timer timer = new System.Timers.Timer();
    int valReg = 30;

    void SomeTimerSettingMethod() { // could also be a constructor
        timer.Elapsed += (sender, eventArgs) => {
            valReg++; // you can just use it
        };
        // ...
    } // SomeTimerSettingMethod

    // ...

} // Motor





最后,匿名方法的好组合没有通过闭包直接访问数据成员,但是匿名方法冻结未使用参数的真实处理程序:





And, finally, the nice combination of anonymous method without direct access to the data members through the closure, but anonymous method freezes up the "real" handler from unused parameters:

class Motor {

        System.Timers.Timer timer = new System.Timers.Timer();
        int valReg = 30;

        void TimerHandler() {
            valReg++; // you can just use it
        } //TimerHandler

        void SomeTimerSettingMethod() { // could also be a constructor
            timer.Elapsed += (sender, eventArgs) => { TimerHandler(); } // as simple as that
            // ...
        } // SomeTimerSettingMethod

        //...

} // Motor 





在大多数情况下,我更喜欢最后一个组合版本。



有问题吗?



-SA


假设我理解正确,我认为你不能按照你的方式做这项工作期待(即out参数的值)。



我的解决方案:



电机上有特定的线程安全属性 class(例如 CurrentPwmAuto & CurrentPreValReg )并在更新这些事件时引发事件。可能选项b会在类级别上产生更多的语义意义,即创建一个单独的类来包含更新的值(假设它被称为Foo,我假设有两个属性 PwmAuto PreValReg )。然后你可以直接举起活动,例如:



Assuming I understand you correctly, I don''t think you can make this work the way you are expecting (i.e. the values on the out parameter).

My solution:

Have specific, thread safe properties on the Motor class (e.g. CurrentPwmAuto & CurrentPreValReg )and raise an event when you update these. Probably "option b" will make more semantic sense at the class level, which is to create a separate class to contain the values of the update (Say it is called Foo, I''m assuming two properties PwmAuto and PreValReg). Then you can just raise the event directly, something like:

class Motor
{
    public event Action<foo> Updated

    public static System.Timers.Timer _timer;
    int valReg = 30;
 
    public void PID(decimal _actualSpeed, Decimal _speedRequest)
    {
 
        _timer = new System.Timers.Timer();
        _timer.Interval = (3000);
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timerAutoset);
        _timer.Enabled = true;
    }
    static void _timerAutoset(object sender, System.Timers.ElapsedEventArgs e)
    {
        /* here I need to work with:
         _actualSpeed
         _speedRequest
         _pwmAuto
         _preValReg
        and send back the last two variables
         */
       if(Updated!= null) //If null, no subscribers
       {
            Updated(new Foo() {PwmAuto = "whatever",  PreValReg = "whatever"});
       }
    }    
}</foo>





然后,用户界面只需要订阅该事件并更新为必要。显然,所有UI更新都需要在UI线程上完成,因此您可能需要重新编写它。如果没有其他解决办法,我会感到惊讶,但这就是我要开始的地方。



Then the UI will just need to subscribe to the event and update as necessary. Obviously all UI updates will need to be done on the UI thread, so you might need to marshal back on to it. I''d be surprised if there aren''t other solutions, but this is where I''d start.


这篇关于将变量传递给类中的定时事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆