【问题标题】:How do I subscribe to raised events and printing together?如何订阅引发的事件并一起打印?
【发布时间】:2011-11-14 14:00:13
【问题描述】:

我一直在研究一个具有 3 个类的程序,其中 2 个类具有以不同间隔重复的计时器,一旦计时器的一个“周期”完成,它就会引发一个带有字符串作为返回的事件。第三类订阅来自其他两个计时器类的事件并将它们打印到屏幕上。效果很好!

但我的问题是它正在单独打印它们。假设第一个计时器类运行,然后每 2 分钟引发一次“hello”,另一个类每秒引发一次“dog”,每次引发事件时,它都会将引发的事件打印到控制台。我希望它每秒打印一次“hellodog”并将第一个计时器(hello)的值存储在私有字段或其他东西中,这样即使计时器(较慢的 2 分钟计时器)还没有,它仍然会打印到屏幕上被解雇了。当 2 分钟计时器触发时,它会将值更新为新值,并且新值会打印到屏幕上,直到再次触发。

如果令人困惑,我很乐意澄清。有点难以解释。

namespace Final
{
    public class Output
    {
        public static void Main()
        {
            var timer1 = new FormWithTimer();
            var timer2 = new FormWithTimer2();

            timer1.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);

            timer2.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer2_NewStringAvailable);
            Console.ReadLine();
        }

        static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
        {
            var theString = e.Value;

            //To something with 'theString' that came from timer 1
            Console.WriteLine(theString);
        }

        static void timer2_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
        {
            var theString2 = e.Value;

            //To something with 'theString2' that came from timer 2
            Console.WriteLine(theString2);
        }
    }

    public abstract class BaseClassThatCanRaiseEvent
    {
        public class StringEventArgs : EventArgs
        {
            public StringEventArgs(string value)
            {
                Value = value;
            }

            public string Value { get; private set; }
        }

        //The event itself that people can subscribe to
        public event EventHandler<StringEventArgs> NewStringAvailable;

        protected void RaiseEvent(string value)
        {
            var e = NewStringAvailable;
            if (e != null)
                e(this, new StringEventArgs(value));
        }
    }

    public partial class FormWithTimer : BaseClassThatCanRaiseEvent
    {
        Timer timer = new Timer();

        public FormWithTimer()
        {
            timer = new System.Timers.Timer(200000);

            timer.Elapsed += new ElapsedEventHandler(timer_Tick); // Everytime timer ticks, timer_Tick will be called
            timer.Interval = (200000);             // Timer will tick evert 10 seconds
            timer.Enabled = true;                       // Enable the timer
            timer.Start();                              // Start the timer
        }

        void timer_Tick(object sender, EventArgs e)
        {
            ... 
            RaiseEvent(gml.ToString());                    
        }
    }


    public partial class FormWithTimer2 : BaseClassThatCanRaiseEvent
    {
        Timer timer = new Timer();

        public FormWithTimer2()
        {
            timer = new System.Timers.Timer(1000);

            timer.Elapsed += new ElapsedEventHandler(timer_Tick2); // Everytime timer ticks, timer_Tick will be called
            timer.Interval = (1000);             // Timer will tick evert 10 seconds
            timer.Enabled = true;                       // Enable the timer
            timer.Start();                              // Start the timer
        }

        void timer_Tick2(object sender, EventArgs e)
        {
            ...
            RaiseEvent(aida.ToString());
        }
    }
}

【问题讨论】:

  • 是的,很抱歉,我不确定...

标签: c# events timer raise


【解决方案1】:

您可以对两个计时器使用相同的事件处理程序。并通过识别发送者来构造输出。 (没有测试代码的语法错误。)

private static string timer1Value = string.Empty;
private static string timer2Value = string.Empty;
private static FormWithTimer timer1;
private static FormWithTimer2 timer2;

public static void Main()
{
    timer1 = new FormWithTimer();
    timer2 = new FormWithTimer2();

    timer1.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);

    timer2.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);
    Console.ReadLine();
}


static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
{
    if (sender == timer1)
    {
        timer1Value = e.Value.ToString();
    }
    else if (sender == timer2)
    {
        timer2Value = e.Value.ToString();
    }

    if (timer1Value != String.Empty && timer2Value != String.Empty)
    {
        Console.WriteLine(timer1Value + timer2Value); 
        // Do the string concatenation as you want.
    }

【讨论】:

    【解决方案2】:

    如果我误解了这个问题,请纠正我,但听起来您想协调您对两个计时器事件的响应(打印“hellodog”)。

    在我看来,最简单的方法是只使用一个计时器,并让计时器的事件处理程序计算调用处理程序的次数,以决定是否采取每秒一次的操作,或者也采取每两分钟一次的动作。

    由于慢速计时器是快速计时器的精确倍数,因此您只需设置一个每秒触发一次的计时器,并且每 120 次调用 1 秒计时器(120 秒 = 2 分钟)执行 2 分钟操作.

    【讨论】:

    • 是否有可能制作另一个每秒关闭的计时器?所以每个引发的事件都会更新“输出”类中的两个新字符串,然后新的计时器会每秒读取一次?这可能吗?
    • @Csharpz:我认为您会遇到计时器触发顺序的问题。我不知道如果应该触发哪个计时器将首先触发“同时。”他们可能会在另一个之前或之后触发几毫秒(尽管我不知道关于顺序和时间的强有力的保证)。
    【解决方案3】:

    我想我明白你想要什么,那就是同步两个计时器的输出。恐怕除了苦苦挣扎之外别无他法。设置一堆布尔变量来跟踪每个事件是否被触发以及同步消息是否被发送到输出。

    【讨论】:

      【解决方案4】:

      这应该做你想做的。

          public static void Main()
          {
              var timer1 = new FormWithTimer();
              var timer2 = new FormWithTimer2();
      
              var value1 = "";
              var value2 = "";
      
              Action writeValues = () => Console.WriteLine(value1 + value2);
      
              timer1.NewStringAvailable += (s, e) =>
              {
                  value1 = e.Value;
                  writeValues();
              };
      
              timer2.NewStringAvailable += (s, e) =>
              {
                  value2 = e.Value;
                  writeValues();
              };
      
              Console.ReadLine();
          }
      

      让我知道这是否正确。干杯。

      【讨论】:

        【解决方案5】:

        第二个(更快的)计时器应该是唯一要打印的计时器。 第一个(较慢的)计时器应该只更新第二个计时器将使用的字符串。

        在“输出”类中(可以放在 Main 之前):

        string string1;
        

        然后:

        static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
        {
            string1 = e.Value;
        }
        
        static void timer2_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
        {
            var theString2 = e.Value;
        
            //To something with 'theString2' that came from timer 2
            Console.WriteLine(string1 + theString2);
        }
        

        【讨论】:

          猜你喜欢
          • 2016-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-29
          • 2018-07-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多