System.Timers.Timer使用的时间比Button_click长10倍

时间:2009-09-24 09:58:44

标签: c# multithreading timer threadpool

我有一个相当流程密集的方法,它接受一个给定的集合,复制项目(Item类正确定义了它的Copy()方法),用数据填充项目并将填充的集合返回给类的集合属性

//populate Collection containing 40 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );

此方法以两种方式调用:on request和System.Timers.Timer对象的'Elapsed'事件。

现在,该系列中的40件商品几乎没有时间。是否通过button_click填充'ad hoc'或者由Timer对象填充。

现在,当我增加集合的大小(另一个具有1000个项目的MyClass对象)时,该过程可预测地需要更长时间,但总共大约6秒。 那很好,没有问题。在初始化(form_load)或被称为ad hoc(button_click)时调用它会保持大约6秒。

//populate Collection containing 1000 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );

但是,System.Timers.Timer对象正在调用相同的方法(如确切的代码行)。而那次经历需要大约60秒(其他运行时间不超过56秒,1分2秒,1分10秒......你明白了)。 同一过程的十倍长!

我知道System.Timers.Timer对象是在Thread-pool中执行的。这可能是原因吗?线程池被赋予较低的优先级,还是整个排队的事情占用了时间?

简而言之,对此更好的方法是什么?使用System.Windows.Forms.Timer在同一个UI线程中执行?

谢谢!

好的,其他一些信息:

定时器操作发生在UI调用的DLL中。主“处理程序”类本身有一组计时器对象,它们都订阅同一个事件处理程序。 处理程序类的初始化工作类似于:

UpdateIntervalTimer tmr = new UpdateIntervalTimer(indexPosition);
tmr.Interval = MyClass.UpdateInterval * 60000; //Time in minutes
tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed);
this.listIntervalTimers.Add(tmr);

我实际上继承了Timer类,给它一个'index'属性(eventArgs也是如此)。这样在一个事件处理程序(tmr_Elapsed)中,我可以识别计时器所针对的MyClass对象并采取行动。

处理程序类已经在自己的线程中运行,并触发自定义事件以深入了解其操作。 该事件在UI中处理(UI控件的交叉线程访问以及诸如此类),并在收到事件处理时显示。对于“初始化”和“临时”调用都是如此(在这些情况下没有问题)。

实际的Elapsed事件如下所示:

private void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
            UpdateIntervalTimer tmr;
            tmr = (UpdateIntervalTimer)sender;

            MyClass c = listOfClasses[tmr.IndexPosition];

            observerEventArguments = new MyHandlerEventArgs("Timer is updating data for " + MyClass.ID);
            MessagePosted(this, observerEventArguments);

            try
            {
                //preparation related code


                MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems);


                observerEventArguments = new ProfileObserverEventArgs(MyClass.ID + ": Data successfully updated");
                MessagePosted(this, observerEventArguments);
            }
            catch (Exception exUpdateData)
            {
                observerEventArguments = new MyHandlerEventArgs("There was an error updating the data for '" + MyClass.ID + "': " + exUpdateData.Message);
                MessagePosted(this, observerEventArguments);
            }
        }

2 个答案:

答案 0 :(得分:1)

嗯,UI线程 可能具有更高的优先级 - 毕竟,它意味着保持UI响应。但是,还有其他事情可能发生。您的方法是否以线程安全的方式访问UI?如果是这样,显然当它不需要在线程之间编组时会更快。

您可以尝试提高线程池线程的优先级,看看是否可以提高性能 - 但除此之外,我们还需要更多信息。

不会建议您在UI线程上执行此操作 - 将UI挂起6秒并不能提供良好的用户体验:(

答案 1 :(得分:0)

当你还在计时器中工作时间隔是否已经过去,导致它多次做同样的工作?这是我认为UI计时器比system.timers.timer / system.threading.timer工作得更快的唯一原因,因为UI计时器是单线程的,并且在完成之前不能再次运行,而其他人可以。