How do I subscribe to raised events and printing together?

时光毁灭记忆、已成空白 提交于 2019-12-23 17:38:06

问题


I have been working on a program that has 3 classes of which 2 of the classes have timers that repeat at different intervals and once one "cycle" of the timer is done it raises an event with a string as return. The 3rd class subscribes to the events from the other two timer classes and prints them to screen. it works great!

But my issue is that it is printing them separately. Lets say that the first timer class runs and then raises "hello" every 2 minutes and the other class "dog" every second and every time an event is raised it prints the raised event to console. I would want it to instead print "hellodog" every second and store the value of the first timer(hello) in a private field or something so it still prints to screen even if the timer(the slower 2 minute timer) hasn't been fired. and when the 2 minute timer fires it updates the value to whatever the new one is and that new value get printed to screen until it fires again.

If it is confusing I will gladly clarify. its kind of hard to explain.

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());
        }
    }
}

回答1:


You can use the same event handler for both timers. And construct the output by identifying the senders. (Didn't test the code for syntax errors.)

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:


Correct me if I misunderstand the question, but it sounds like you want to coordinate your response to the two timer events (print "hellodog").

It seems to me that the easiest way to do this is to just use a single timer, and have the timer's event handler count the number of times the handler has been invoked to decide whether to take the once-per-second action, or also take the once-per-two-minutes action.

Since the slow timer is an exact multiple of your fast timer, you would set just one timer that triggers every second, and also do the 2-minute action every 120 invocations of the 1 second timer (120 seconds = 2 minutes).




回答3:


I think I understand what you want and that is to synchronize the output of both timers. I am afraid there is no way to do it other than to slog through it. Set up a bunch of Boolean variables that track whether each event fired and whether the synchronized message was sent to the output.




回答4:


This should do what you want.

    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();
    }

Let me know if this is right. Cheers.




回答5:


The second (quicker) timer should be the only one to print. The first (slower) timer should only update a string which the second timer will use.

In the 'Output' class (you can put it before Main):

string string1;

and then:

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);
}


来源:https://stackoverflow.com/questions/7375452/how-do-i-subscribe-to-raised-events-and-printing-together

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!