如何使用System.Timers.Timer来控制winform的进度 [英] how to use System.Timers.Timer to control a progress in winform

查看:501
本文介绍了如何使用System.Timers.Timer来控制winform的进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用Timer在表单中执行进度条时,我发现只有在消耗时间函数结束后,进度条才能执行步骤。我不知道为什么。帮助我。

以下是我的代码。

when I use Timer to performstep a progressbar in a form,I find only after the consuming time function ends,the progress bar can perform step.I don't know why.Help me.
Below is my code.

public partial class Form1 : Form
    {
        System.Timers.Timer aTimer;
        public Form1()
        {
            InitializeComponent();
            aTimer = new System.Timers.Timer();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            aTimer = new System.Timers.Timer(2000);
            aTimer.Elapsed += new System.Timers.ElapsedEventHandler(aTimer_Elapsed);
            aTimer.Enabled = true;
            int n = Convert.ToInt32(textBox1.Text);
            long m = ComputeFibonacci(n);
            Console.WriteLine("Fibonacci:" + m);
            aTimer.Enabled = false;
        }
         void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
            if (InvokeRequired)
            {
                this.Invoke(new Action(progressBar1.PerformStep));
                Application.DoEvents();
            }
            else
            {
                progressBar1.PerformStep();
                Application.DoEvents();
            }
            Console.WriteLine(progressBar1.Value);
        }
        /// <summary>
         /// Compute  Fibonacci
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        long ComputeFibonacci(int n)
        {
            // The parameter n must be >= 0 and <= 91.
            // Fib(n), with n > 91, overflows a long.
            if ((n < 0) || (n > 91))
            {
                throw new ArgumentException(
                    "value must be >= 0 and <= 91", "n");
            }
            long result = 0;
            // Abort the operation if the user has canceled.
            // Note that a call to CancelAsync may have set 
            // CancellationPending to true just after the
            // last invocation of this method exits, so this 
            // code will not have the opportunity to set the 
            // DoWorkEventArgs.Cancel flag to true. This means
            // that RunWorkerCompletedEventArgs.Cancelled will
            // not be set to true in your RunWorkerCompleted
            // event handler. This is a race condition.
            if (n < 2)
            {
                result = 1;
            }
            else
            {
                result = ComputeFibonacci(n - 1) +
                         ComputeFibonacci(n - 2);
            }

            return result;
        }

推荐答案

你必须启动一个单独的线程来进行计算,因为你正在调用斐波那契计算从事件处理程序中的方法,在按钮单击事件的处理程序返回之前,不会处理所有其他GUI事件。在你的情况下,这将不会发生,直到斐波纳契数的计算结束。



问候,

- 曼弗雷德
You'll have to start a separate thread to do the calculation because you're calling the fibonacci computing method from within an event handler all other GUI events will not be processed until the handler of the button click event has returned. In your case this will not happen until the computation of the fibonacci number has finished.

Regards,
— Manfred


我可以工作,但几乎没有任何意义,但原因如下:你需要显示斐波纳契计算的进度,但你只需显示计时器事件的数量。你不会显示任何有用的东西,这不是很明显吗?



解决方案非常明显:在一个单独的线程中执行Fibonacci计算。通过这种方式,您始终可以知道您的迭代次数,因此您可以相应地通知进度条。由于Fibonacci算法是线性的(Fibonacci序列本身是根据算法定义的),迭代次数也将与时间成比例,即,这是O(N)时间复杂度。 >


当然,因​​为所有UI操作(包括进度条更新)都应该在应用程序的UI线程中完成,所以也可以使用 System.Windows.Forms来完成.Control.Invoke 。只有您不需要检查 InvokeRequired - 在此方案中始终需要。主要的是:不要调用 Application.DoEvents 。请不要。



请参阅:

http://en.wikipedia.org/wiki/Big_O_notation [ ^ ],

http://en.wikipedia.org/ wiki / Time_complexity [ ^ ],

http://en.wikipedia.org/wiki/Computational_complexity_theory [ ^ ],

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx [ ^ ],

http://msdn.microsoft.com/en-us/library/system.windows.forms .control.invokerequired.aspx [ ^ ]。



就是这样。



请注意使用计时器通常是一个坏主意,即使它适用。线程通常更好,因为它很容易表示一些线性行为。此外,定时器固有地存在可靠性问题。例如,当前一个事件调用的处理程序的执行仍然不完整时,是否曾尝试在调用新的计时器事件时解决该问题?线程方法不存在这样的问题。



一个小建议:从一开始就摆脱自动生成的名称,如Form1,Button1_Click, progressBar1,等等。它们不仅丑陋而且令人生气,它们不可读,不会让你知道它们的作用,语义,甚至违反(好的)Microsoft命名约定:没有数字,没有下划线。使用Visual Studio的重构引擎重命名所有名称。切勿使用自动生成的名称,使用语义敏感的名称。



-SA
I could work, but makes little to no sense, but the following reason: you need to show the progress in your Fibonacci calculation, but you simply show then number of timer events. You are going to show nothing useful, isn't it obvious?

The solution is quite obvious: perform Fibonacci calculation in a separate thread. In this way, you always know at what iteration you are, so you can notify the progress bar accordingly. As Fibonacci algorithm is linear (Fibonacci sequence is itself defined in terms of algorithm), the number of iteration will also be proportional to time, that is, this is O(N) time complexity.

Of course, as all UI operations, including progress bar update, should be done in your application's UI thread, also do it using System.Windows.Forms.Control.Invoke. Only you don't need to check InvokeRequired — it is always required in this scenario. And main thing here it: don't call Application.DoEvents. Just don't.

Please see:
http://en.wikipedia.org/wiki/Big_O_notation[^],
http://en.wikipedia.org/wiki/Time_complexity[^],
http://en.wikipedia.org/wiki/Computational_complexity_theory[^],
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx[^].

That's it.

Note that using a timer is generally a bad idea even when it is applicable. A thread is very typically better, as it's easy to represent some linear behavior. Also, timers inherently present problems with reliability. For example, did you ever tried to address the problem when a new timer event is invoked when the execution of a handler called by a previous event is still incomplete? The thread approach does not present such problems.

One little advice: from the very beginning, get rid of auto-generated names like "Form1", "Button1_Click", "progressBar1", etc. Not only they are ugly and irritating, they are not readable, does not give you the idea on what they do, semantically, and they even violate (good) Microsoft naming conventions: no numerals, no underscore. Rename all names using the refactoring engine of Visual Studio. Never use auto-generated names, use semantically sensible names.

—SA


这篇关于如何使用System.Timers.Timer来控制winform的进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆