如何在C#中使用计时器和事件?

时间:2011-09-10 21:54:52

标签: c# events timer

好的,所以我一直在研究一个程序。我有3节课。其中2个类具有以不同的间隔重复的定时器,并且一旦定时器的一个“循环”完成,它就会引发一个带有字符串的事件作为返回。第三类订阅来自其他两个计时器类的事件,并使用诸如print to console之类的字符串进行处理。

但我无法让它工作,它编译得很好,但它只是打开一个控制台,然后快速关闭它(没有输出)。你们有什么不对劲吗?

感谢

CODE:

using System;
using System.Timers;
using System.Text;
using System.Xml;
using System.IO;
using System.IO.Ports;
using System.IO.MemoryMappedFiles;
using System.Net;

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

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

            //To something with 'theString' that came from timer 1
            Console.WriteLine("Just got: " + 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("Just got: " + theString2);
        }
    }

    public abstract class BaseClassThatCanRaiseEvent
    {
        /// <summary>
        /// This is a custom EventArgs class that exposes a string value
        /// </summary>
        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;

        /// <summary>
        /// Helper method that raises the event with the given string
        /// </summary>
        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)
        {
            var url = @"https://gmail.google.com/gmail/feed/atom";
            var USER = "usr";
            var PASS = "pass";

            var encoded = TextToBase64(USER + ":" + PASS);

            var myWebRequest = HttpWebRequest.Create(url);
            myWebRequest.Method = "POST";
            myWebRequest.ContentLength = 0;
            myWebRequest.Headers.Add("Authorization", "Basic " + encoded);

            var response = myWebRequest.GetResponse();
            var stream = response.GetResponseStream();

            XmlReader reader = XmlReader.Create(stream);
            System.Text.StringBuilder gml = new System.Text.StringBuilder();
            while (reader.Read())
                if (reader.NodeType == XmlNodeType.Element)
                    if (reader.Name == "fullcount")
                    {
                        gml.Append(reader.ReadElementContentAsString()).Append(",");
                    }
            RaiseEvent(gml.ToString());
            // Console.WriteLine(gml.ToString());

        }

        public static string TextToBase64(string sAscii)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] bytes = encoding.GetBytes(sAscii);
            return System.Convert.ToBase64String(bytes, 0, bytes.Length);
        }
    }


    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)
        {
            using (var file = MemoryMappedFile.OpenExisting("AIDA64_SensorValues"))
            {
                using (var readerz = file.CreateViewAccessor(0, 0))
                {
                    var bytes = new byte[194];
                    var encoding = Encoding.ASCII;
                    readerz.ReadArray<byte>(0, bytes, 0, bytes.Length);

                    //File.WriteAllText("C:\\myFile.txt", encoding.GetString(bytes));

                    StringReader stringz = new StringReader(encoding.GetString(bytes));

                    var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
                    using (var reader = XmlReader.Create(stringz, readerSettings))
                    {
                        System.Text.StringBuilder aida = new System.Text.StringBuilder();
                        while (reader.Read())
                        {
                            using (var fragmentReader = reader.ReadSubtree())
                            {
                                if (fragmentReader.Read())
                                {
                                    reader.ReadToFollowing("value");
                                    //Console.WriteLine(reader.ReadElementContentAsString() + ",");
                                    aida.Append(reader.ReadElementContentAsString()).Append(",");
                                }
                            }
                        }
                        RaiseEvent(aida.ToString());
                        //Console.WriteLine(aida.ToString());
                    }
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:4)

您正在退出Main方法(这将停止您的申请)而不等待您的结果。只需添加Console.ReadLine()即可等待:

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

答案 1 :(得分:4)

您的程序在完成Main方法时正在关闭。要使项目不关闭,您可以在方法

的末尾添加Console.ReadLine()

答案 2 :(得分:3)

当Main()函数退出时,程序结束。 你在方法中做的是初始化定时器并退出。 您需要实现一种机制来等待某些条件退出,如:

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); 
            while (NotExit()){
               Thread.Sleep(1000);
            }
        } 

通过这种方式,您可以实现一些NotExit()方法,该方法将根据特定条件停止主线程(例如:用户按下键等等)。 一个好的做法:在退出之前,尝试轻轻地停止任何正在运行的线程(每个Timer tick创建一个新线程),因此为eack timer tick执行的代码将运行到一个单独的线程中。一种方法是使用Join()方法。