虽然计时器内的序列在C#中打勾

时间:2013-10-08 14:37:35

标签: c# timer while-loop

我在C#中有一个1秒的计时器,其中有一个while序列。我的问题是,如果while序列在1秒之前没有完成,计时器是否会打勾,并从头开始重新启动?

代码的一部分在下面,它的作用是循环选定的对象并改变一些东西。因此,如果选择了很多对象并且我需要超过1秒来更改它们,它们都会被更改吗?

P.S。我实际上希望循环被打破;只会错误地选择大量的物体,但我只是想确保我避免这种可能性。 :)

private void timer1_Tick(object sender, EventArgs e)
        {
            TSM.ModelObjectEnumerator myEnum = null;
            myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();

            while (myEnum.MoveNext())
            {
                if (myEnum.Current != null)
                {....}
            }
         } 

7 个答案:

答案 0 :(得分:5)

是的,计时器滴答可以同时发生。这意味着您的计时器必须是线程安全的。

除了以外的UI计时器类(WinForms / WPF)。他们的tick函数在UI线程上运行。使用DoEvents,即使存在另一个避免DoEvents的原因,也可能导致重入。

答案 1 :(得分:1)

从处理程序的名称我假设您使用的是System.Windows.Forms.Timer,它是单线程的。这意味着Tick事件将在前一个事件结束后触发。要打破循环,您必须在另一个线程中执行代码并使用退出条件。

这就是我通常的做法:

private bool running;
private bool restart;

private void DoWork(object item)
{
    running = true;    
    TSM.ModelObjectEnumerator myEnum = null;
    myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();

    while (myEnum.MoveNext() && !restart)
    {       
        //do your stuff
        if (myEnum.Current != null) {....}
    }

    if(restart)
    {
        restart = false;
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (running)
        restart = true;
    else            
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));            
}

答案 2 :(得分:0)

解决方法是在while事件的顶部禁用计时器,并在退出while事件时重新启用它。

答案 3 :(得分:0)

while循环不会被破坏,因为计时器再次勾选。但无论如何,最好的办法是在事件处理程序的开头禁用计时器,并在最后重新启用它。

答案 4 :(得分:0)

你总是可以尝试类似的东西,这样你就可以让多个计时器勾选并启动进程。写在记事本中,请原谅任何大规模的拼写错误

private Timer _systemTimer = null;

public MyApp()
{
_systemTimer = new Timer("how ever you set your 1 second);
// Create your event handler for when it ticks over
_systemTimer.Elapsed += new ElapsedEventHandler(systemTimerElapsed);
}

protected void systemTimerElapsed(object sender, ElapsedEventArgs e)
{
_systemTimer.Stop();
//Do what you need to do
_systemTimer.Start();
//This way if it takes longer than a second it won't matter, another time won't kick off until the previous job is done 
}

答案 5 :(得分:0)

我会让你很容易;在另一个后台线程中使用Thread.Sleep()并完成它!

如果您知道何时完成,只需使用AutoResetEvent来保持线程同步。 如果您对更新没有任何控制没有回调,时间未知我建议增加您的计时器间隔!

var thread = new Thread((ThreadStart)delegate
        {
         While(true)
           {
             TSM.ModelObjectEnumerator myEnum = null;
             myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();
             while (myEnum.MoveNext())
              {
                  if (myEnum.Current != null)
                 {....}
              }

              Thread.Sleep(1000);
           }
         }
    thread.Start();

答案 6 :(得分:0)

从txtString中获取字符串中的每个char,并使用timerControl

逐个写入标签
int g = 0;
private void timerString_Tick(object sender, EventArgs e)
{
    string a = txtString.Text;
    int em = txtString.TextLength;
    if (g < em)
    {
        lblString.Text = lblString.Text + a[g];
        g++;
    }
    else timerString.Stop();
}

来自

private void btnStringStart_Click(object sender, EventArgs e)
{
    timerString.Start();
    lblString.Text = "";
}