我将Timer继承后,定义了一个10维的myTimer数组
现在让其同时启动,但是 只能 1秒钟启动2个左右
代码片段:                        double timeNum = 3000;
                        timerArray[i] = new MyTimer(timeNum);
                        timerArray[i].Elapsed += new System.Timers.ElapsedEventHandler(timerArray_Elapsed);
                        timerArray[i].AutoReset = false;
                        timerArray[i].Tag1 = i;
 
                        timerArray[i].Tag2 = 0;
                        sPortArray[i].spClose();
                        timerArray[i].Start();
        private void timerArray_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MyTimer theTimer = (MyTimer)sender;            int i = (int)theTimer.Tag1;
            int redTemp = (int)theTimer.Tag2;            Console.WriteLine("inTimer=" + DateTime.Now.ToString() + writePorts[i]);
部分结果:COM309:45:04.7812500
COM509:45:04.7968750
COM609:45:04.8125000
COM709:45:04.9531250
COM809:45:04.9687500
COM909:45:04.9843750
COM1009:45:05.1093750
COM1109:45:05.1250000
COM1209:45:05.1406250
COM1309:45:05.2656250          启动时间
inTimer=2009-9-17 9:45:07COM3
inTimer=2009-9-17 9:45:07COM5
inTimer=2009-9-17 9:45:08COM6
inTimer=2009-9-17 9:45:08COM7
inTimer=2009-9-17 9:45:09COM8
inTimer=2009-9-17 9:45:09COM9
inTimer=2009-9-17 9:45:10COM10
inTimer=2009-9-17 9:45:10COM11
inTimer=2009-9-17 9:45:11COM12
inTimer=2009-9-17 9:45:11COM13              Timer 执行事件的时间  从07秒到11秒 持续近4秒时间
2009-9-17 9:45:12
COM5kn|=================2009-9-17 9:45:12
2009-9-17 9:45:12
COM3kn|=================2009-9-17 9:45:121、这是什么原因?
2、怎么解决?
我就是想让其能同时启动,当然是宏观意义上的了。在1、2秒内总该执行完吧。。

解决方案 »

  1.   

    正常现象,
    处理器的对线程的切换时间为30毫秒,而你写法基本上一个接一个timerArray_Elapsed去调用,而个timerArray_Elapsed所用的时候一定不会超过30毫秒,看结果,两个timerArray_Elapsed所用的时间超过30毫秒,完成后myTimer[i]线程退出,刚好去执行myTimer[i+1]代码,这样说不知道你明不明白在timerArray_Elapsed中加入Thread.Sleep(1000);你会看到你要的结果
      

  2.   

    这个是线程池的吞吐量问题导致的把。
    我的代码能实现你的要求:using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                System.Timers.Timer[] timerArray = new System.Timers.Timer[10];
                for (int i = 0; i < 10; i++)
                {
                    timerArray[i] = new System.Timers.Timer();
                    timerArray[i].Interval = 3000;
                    timerArray[i].Elapsed += new System.Timers.ElapsedEventHandler(Program_Elapsed);
                    timerArray[i].AutoReset = false;
                    timerArray[i].Enabled = true;
                    Console.WriteLine("Main: " + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString());
                }
                System.Threading.Thread.Sleep(5000);
            }        static void Program_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                System.Timers.Timer theTimer = (System.Timers.Timer)sender;
                Console.WriteLine("inTimer: " + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString());
            }
        }
    }
      

  3.   


    测试后,大概明白你说的了。
    就是说,每个线程执行时间最多是500ms(呵呵,你想当然60ms=1s么 - -)。
    1、若当前线程执行完了,就执行其他线程,
    就像楼上的程序一样。
    2、没有执行完,就可以继续执行,但一次时间片的时间是500ms即:只能执行500ms的时间。。
    之后呢,按照你的意思 Thread.Sleep(10000); (我改成了10s)加进去,想让线程主动放弃cpu资源么。但是没有效果啊。这样反而可以实现 楼上那种代码的  我的问题现象。如果时间片真是500ms这样的话,线程的精度太低了。。该怎样设置,怎样解决呢?不知道我理解是否有错误,请指正。
      

  4.   

    难道 System.Timers.Timer 的实现机制和普通线程有差别?
    或者说 不是由于 线程时间片的原因?
      

  5.   


    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Timers;
    using System.Threading;namespace timerStart
    {
        class Program
        {
            private MyTimer[] timerArray;
            Thread[] tArray;
            private int length;        public void Init()
            {
                length = 10;
                timerArray = new MyTimer[length];
                for (int i = 0; i < length; i++)
                {
                    timerArray[i] = new MyTimer(3000);
                    timerArray[i].AutoReset = false;
                    timerArray[i].Elapsed += new ElapsedEventHandler(Program_Elapsed);
                    timerArray[i].Start();
                    Console.WriteLine(i + "\t" + DateTime.Now.TimeOfDay.ToString());
                }
                Thread.Sleep(10000);
            }
            public void Init2()
            {
                length = 10;
                tArray=new Thread[length];
                for (int i = 0; i < length; i++)
                {
                    tArray[i] = new Thread(new ThreadStart(Program_Thread));
                    tArray[i].IsBackground = true;
                    //tArray[i].Start();
                    Console.WriteLine(i + "\t" + DateTime.Now.TimeOfDay.ToString());
                }
                Thread.Sleep(3000);
                for (int i = 0; i < length; i++)
                    tArray[i].Start();
                Thread.Sleep(10000);        }        void Program_Elapsed(object sender, ElapsedEventArgs e)
            {
                Console.WriteLine("inTimer==="+sender.ToString()+"\t"+DateTime.Now.TimeOfDay.ToString());
                Thread.Sleep(10000);
            }        void Program_Thread()
            {
                Thread.Sleep(1);
                Console.WriteLine("inTimer===" + "\t" + DateTime.Now.TimeOfDay.ToString());
                //int i=10000;
                //while (i > 0)
                //{
                //    i--;
                //    if (i % 1000 == 0)
                //        Console.WriteLine(i);
                //}
                while (true)
                { }
            }
            static void Main(string[] args)
            {
                Program p = new Program();
                p.Init2();
                
            }
        }    public class MyTimer : System.Timers.Timer
        {
            private object tag1, tag2, tag3, tag4;
            public MyTimer()
                : this(1000)
            { }
            public MyTimer(double _interval)
                : base()
            {
                this.Interval = _interval + 1;
            }
            public object Tag1 { get { return tag1; } set { tag1 = value; } }
            public object Tag2 { get { return tag2; } set { tag2 = value; } }
            public object Tag3 { get { return tag3; } set { tag3 = value; } }
            public object Tag4 { get { return tag4; } set { tag4 = value; } }
        }
    }
    我这样测,的确基本如你所说,但是这个 Timer 和Tread 不一样。sleep 不管用
      

  6.   

    C#中有三个Timer
    System.Threading.Timer;
    System.Windows.Forms.Timer;
    三面两个原理一样你用的是:System.Timers.Timer,Thread.Sleep对它确定不管理用,这个Timer是用服务器上的时间为参考,与多线程没有关系,只要到了时间就使用当前所在的线程执行代码,
      

  7.   

    随便说下,不要在使用这个System.Timers.Timer,说不定下个新版本就会不支持它了
      

  8.   

    System.Threading.Timer[] timer;
    static void Go()
    {
        for (int i = 0; i < cnt; i++)
        {
           timer[i] = new Timer(new TimerCallback(YourMethod), i, 0, Timeout.Infinite);
        }
    }static void YourMethod(objece state)
    {
       //doing sth
       Thread.Sleep(1000);
       timer[int.Parse(state.ToString())].Change(1000, Timeout.Infinite);
    }
      

  9.   

    这个说法靠不住脚,这个类没什么不好,有些场合甚至是最佳选择,因为它可以更精确地按时引发事件。楼主的问题其实不是System.Timers.Timer本身造成的,由于多个事件几乎同时引发,一个线程来不及处理,要多个线程同时处理,这时就必须在线程池中申请线程来处理,这个申请需要耗时,那个间隔是申请线程导致的时间损耗,如果一个线程能来得及处理,或者不需要10个线程来处理,将大大提高响应速度。你可以将你第二次给的代码中的Sleep都去掉看看是不是很快就输出了。
      

  10.   

    我再给你一个很给力的示例,更加说明这个道理:    class Program
        {
            private MyTimer[] timerArray;
            private int length;        public void Init()
            {
                length = 10;
                timerArray = new MyTimer[length];
                Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId);
                for (int i = 0; i < length; i++)
                {
                    timerArray[i] = new MyTimer(30000);
                    timerArray[i].AutoReset = true;
                    timerArray[i].Elapsed += new ElapsedEventHandler(Program_Elapsed);
                    timerArray[i].Start();
                    Console.WriteLine(i + "\t" + DateTime.Now.TimeOfDay.ToString());
                }
            }        void Program_Elapsed(object sender, ElapsedEventArgs e)
            {
                Console.WriteLine("当前线程ID:"+Thread.CurrentThread.ManagedThreadId+"。inTimer===" + sender.ToString() + "\t" + DateTime.Now.TimeOfDay.ToString());
                Thread.Sleep(10000);
            }        static void Main(string[] args)
            {
                Program p = new Program();
                p.Init();
                Console.Read();
            }
        }    public class MyTimer : System.Timers.Timer
        {
            private object tag1, tag2, tag3, tag4;
            public MyTimer()
                : this(1000)
            { }
            public MyTimer(double _interval)
                : base()
            {
                this.Interval = _interval + 1;
            }
            public object Tag1 { get { return tag1; } set { tag1 = value; } }
            public object Tag2 { get { return tag2; } set { tag2 = value; } }
            public object Tag3 { get { return tag3; } set { tag3 = value; } }
            public object Tag4 { get { return tag4; } set { tag4 = value; } }
        }我在这里输出了线程ID,可以看到分别在不同的线程中执行,由于使用了Sleep,CPU占用率几乎为0,不存在CPU来不及响应的问题。时间间隔设为30秒,为了可以更加清楚的看清现象,同时将循环打开,每隔30秒引发一次事件。
    你会看到这样的现象:第一个30秒后,花了很长时间才将10个事件执行完毕,但是第二个30秒(即第一个事件开始执行的时间过后30秒,很精准)开始,10个事件同时执行完毕,几乎没有任何时间间隔。