【问题标题】:Explain ASP.NET Events解释 ASP.NET 事件
【发布时间】:2009-08-25 19:02:08
【问题描述】:

另见:

understanding events and event handlers in C#

作为一名网络开发人员,我通常不必为对象构建自己的事件,因为大多数事件都是页面固有的。但是,现在我进入了一个非常复杂的(网络)项目,我认为我可能不得不使用它们。我刚刚阅读了 Pro VB 2008 and the .NET 3.5 Platform 中有关事件、代表和 lambdas 的一章(第 11 章),虽然我对正在发生的事情有了更好的了解,但我仍然无法在 when确切地使用它们以及如何使用它们。我理解他们的实现,但是书中的例子有点做作。

我希望对事件主题有更多了解的人可以为我提供一个非常可靠的例子。

对于我的实际应用程序,我正在尝试使用一个事件来通知我何时更新了某个项目(某个类,名为 OrderItem)并根据它是否已更新来执行操作。我考虑过使用标志/布尔属性,但我知道这听起来不对,现在是我学习如何正确使用事件的时候了。

非常感谢!

编辑好的,所以我想澄清一下,当它所做的只是调用一个方法时,调用一个事件有什么意义?为什么不简单地调用该方法?这也不是重复的,因为我从概念上讲,她想具体了解处理程序。另外,我想知道使用事件或“标志”属性之间有什么区别。人们所说的“订阅”事件是什么意思?

【问题讨论】:

  • 已经有一些很好的答案。
  • Rex 在#803242 中的回答几乎是我会逐字发布的内容。从那里开始,如果您有任何问题,请重新发布。
  • 不要把它当作骗子来关闭。有几点区别:1,OP 不是询问如何使用,而是询问何时使用事件;2,OP 询问事件是否是他们当前项目的方式。

标签: vb.net events event-handling delegates


【解决方案1】:

假设您有一个电梯系统,上下移动的部分称为 ElevatorCar。当一个人按下按钮去 5 楼时,ElevatorController 调用 ElevatorCar.RequestToFloor(5) 方法是有意义的。现在,当汽车实际到达 5 楼时,它会引发像 ArrivedAtFloor 这样的事件,并传递 5 作为参数。 ElevatorController 类将订阅 ElevatorCar 类的 ArrivedAtFloor 事件。

这都是因为 ElevatorCar 类不“知道”任何关于 ElevatorController 类的信息,但 ElevatorController 类确实知道 ElevatorCar 类。因此,ElevatorCar 类通过方法获得指令,并通过事件通知外部世界发生的事情。

这有意义吗?

编辑:

好的,首先,请阅读“另请参阅”链接中列出的出色答案(假设您已经这样做了)。事件基本上是一个对象,它说“如果你想让我在 X 发生时给你打电话,然后在 here 注册你的方法”。向事件注册事件处理程序是“订阅”。这允许封装。例如,您可以编写一次 ElevatorCar 类,然后由许多其他类多次使用。

至于使用事件和调用方法的区别,你要问自己,ElevatorCar 是否知道 ElevatorController 类。如果 ElevatorController 调用 ElevatorCar.GoToFloor(x),ElevatorCar 类如何在不存储对 ElevatorController 的引用的情况下“回调”到 ElevatorController?这意味着调用必须变为 ElevatorCar.GoToFloor(int floor, ElevatorController ctrlr)。然后 ElevatorCar 类最终必须调用 ctrlr.ArrivedAtFloor(floor)。但是你会遇到很多复杂的情况......如果有不止一辆车怎么办?您可能必须调用 ctrlr.ArrivedAtFloor(floor, this)。传递对您自己的引用并不是最佳选择。

至于只是设置一个属性,其他类怎么知道来读取属性呢?唯一的方法是一遍又一遍地轮询属性以检查它是否发生变化。当然,您可以通过实现 INotifyPropertyChanged 来解决这个问题,但是您又回到了事件中!

【讨论】:

  • 这与仅让类调用方法而不是通过事件连接有什么不同?
【解决方案2】:

事件是Inversion of Control (IoC) 模式的一种特殊情况。传统的控制流,调用者调用被调用者的方法(就像你建议的那样)。使用 IoC(以及事件),我们围绕应用程序控件进行更改,而不是告诉被调用者要做什么,而是告诉被调用者在我们感兴趣的事情发生时通知我们。

考虑Timer 的情况。我想每 5 秒收到一次通知(比如说)。我不想一直poll the timer(“是时候了吗?是时候了吗?是时候了吗?”)。相反,我想反转我的应用程序的流控制。我想告诉计时器:“时间到了,请通过调用这个方法告诉我。”这样,控制是“反转”的,被调用者正在调用调用者的方法!

考虑下面的代码...

using System;
using System.Timers;

namespace TestTimer
{
    class Program
    {
        static void Main(string[] args)
        {
            // create my timer.
            var t = new System.Timers.Timer(1000);

            // register for notification
            // tell the timer, "when it's time, call TimerGoesOff method"
            t.Elapsed += new ElapsedEventHandler( TimerGoesOff );

            // start the timer
            t.Start();

            // wait
            Console.ReadLine();
        }

        // this gets called when the timer goes off
        public static void TimerGoesOff(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("The Time is " + e.SignalTime);
        }
    }
}

我没有在 Timer 上调用一个方法来询问它何时会再次关闭(如您所建议的那样),而是告诉它,“当您关闭时,调用 TimerGoesOff”方法。现在,我可以做一些工作,而不仅仅是等待计时器响起。考虑这段代码...

using System;
using System.Threading;
using System.Timers;

namespace TestTimer
{
    class Program
    {
        static void Main(string[] args)
        {
            // create my timer.
            var t = new System.Timers.Timer(1000);

            // register for notification
            t.Elapsed += new ElapsedEventHandler( TimerGoesOff );

            // start the timer
            t.Start();

            // do some work while timer is going
            new Thread(() => DoWork()).Start();

            Console.ReadLine();
        }

        // this gets called when the timer goes off
        public static void TimerGoesOff(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("The Time is " + e.SignalTime);
        }

        public static void DoWork()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine( "Working ..." );
                Thread.Sleep( 1000 );
            }
        }
    }
}

现在,我得到的输出类似于 ...

Working ...
The Time is 8/25/2009 1:05:59 PM
Working ...
Working ...
The Time is 8/25/2009 1:06:00 PM
Working ...
The Time is 8/25/2009 1:06:01 PM
Working ...
The Time is 8/25/2009 1:06:02 PM
The Time is 8/25/2009 1:06:03 PM

我使用Timer.Elapsed Event 更改了我的应用程序的控制流。我可以在“等待”计时器事件发生脉冲的同时下班工作。 IoC 和事件使这成为可能。

这在用户界面中尤其明显(呵呵)。我不想一直问“用户做了什么了吗?用户做了什么了吗?” (这就是过去的方式)。相反,我告诉 Controls,例如,“当用户点击你时,让我知道”。这样一来,我就可以开始做其他很棒的事情,同时仍能响应用户。

【讨论】:

  • 这是一个有趣且有用的答案......虽然在 VB 中,lambda 必须返回值:\
猜你喜欢
  • 2016-05-31
  • 2011-11-07
  • 1970-01-01
  • 2020-03-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
相关资源
最近更新 更多