当方法运行时无法单击按钮

时间:2013-03-14 20:21:13

标签: c# winforms scroll

   private void AddMyScrollEventHandlers()
   {
       VScrollBar vScrollBar1 = new VScrollBar();
   }

   private void button1_Click(object sender, EventArgs e)
   {
       while (true)
       {
           if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
           {
               vScrollBar1.Value = vScrollBar1.Value + 1;    
               label1.Text = vScrollBar1.Value.ToString();                       
           }       
           else 
           {         
               break;      
           }

           System.Threading.Thread.Sleep(200);
       }
   }

   private void button2_Click(object sender, EventArgs e)
   {
       // vScrollBar1.Scroll
   }

我是C#的新手。我正在做卷轴。我想要的是,如果有人点击button1然后滚动自动移动到最后我想在label1中显示渐变值。当有人点击button2滚动停止时。

现在问题是label1没有显示值的逐渐变化。它在滚动停止时显示一次值。

当滚动继续i时,e在while循环工作时我无法点击button2。实际上我甚至无法点击表格。

有人请告诉我如何做到这一点。

3 个答案:

答案 0 :(得分:5)

这是因为执行任务的线程正忙,而且它是更新UI的相同线程。您可以使用多线程解决方案。看一眼 BackgroundWorker

答案 1 :(得分:1)

所有UI事件都在应用程序的主线程中运行,因此应用程序一次只能处理一个事件。当应用程序处理事件时,不会处理任何其他事件。

由于您定期进行与UI相关的工作,最好的选择是使用Timer类:

  1. Timer从工具箱中删除到表单中。
  2. 在属性窗口中,将间隔设置为200。
  3. 双击计时器对象以创建Tick事件处理程序。
  4. 将此代码放在新创建的timer1_Tick方法中:

     if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
     {
         vScrollBar1.Value = vScrollBar1.Value + 1;    
         label1.Text = vScrollBar1.Value.ToString();                       
     }       
     else 
     {         
         timer1.Stop();
     }
    
  5. 更改您的方法如下:

    private void AddMyScrollEventHandlers()
    {
        timer1.Start();
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
        timer1.Stop();
    }
    
  6. 现在你已经完成了。

答案 2 :(得分:0)

我建议使用{em> Agustin Meriles 建议的BackgroundWorker控件。但是,需要注意的另一个重要事项是,您应该使用Control.Invoke(...)方法从另一个线程更新控件。

我修改了您的代码,在示例应用程序中对其进行了测试,但它似乎正常运行。

首先,向您的表单添加一个新的BackgroundWorker控件,并将backgroundWorker1_DoWork分配给其DoWork事件。

然后,您可以使用以下代码:

private void button1_Click(object sender, EventArgs e)
{
    //code from here is moved to BackgroundWorker control
    backgroundWorker1.RunWorkerAsync();
}

private void button2_Click(object sender, EventArgs e)
{

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    //while (true)
    //the condition directly in the while looks more clear to me
    while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
    {
        //update controls using Invoke method and anonymous functions
        vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });

        label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });

        //when called inside BackgroundWorker, this sleeps the background thread, 
        //so UI should be responsive now
        System.Threading.Thread.Sleep(200);
    }
}

如果您在使用此代码时遇到任何问题,请告知我们。

<强>更新

如评论中所述,您还可以使用ProgressChanged的{​​{1}}事件。它需要在代码中进行一些更改,但在这种情况下更合适。您可以在此处找到有关它的一些信息:http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx

如果您不打算在BackgroundWorker循环中添加任何其他代码以及更多处理,您也可以按照 MD.Unicorn 的建议使用while控件他的回答。