C# 如何设置ProgressBar以在计时器的每个滴答声处递增?

C# 如何设置ProgressBar以在计时器的每个滴答声处递增?,c#,winforms,C#,Winforms,我有一个简单的表单,它应该启动一个计时器,执行一个耗时的操作,并在操作运行时以一定的间隔更新进度条。现在,耗时的操作绑定到一个SearchButton。但是,进度条不会发生任何变化,即使耗时的操作(在本例中为下载)确实需要几秒钟: public partial class Form1 : Form { System.Windows.Forms.Timer searchProgressTimer; public Form1() { InitializeCo

我有一个简单的表单,它应该启动一个计时器,执行一个耗时的操作,并在操作运行时以一定的间隔更新进度条。现在,耗时的操作绑定到一个
SearchButton
。但是,进度条不会发生任何变化,即使耗时的操作(在本例中为下载)确实需要几秒钟:

public partial class Form1 : Form
{
    System.Windows.Forms.Timer searchProgressTimer;

    public Form1()
    {
        InitializeComponent();
        this.searchProgressTimer = new System.Windows.Forms.Timer();
    }

    private void InitializeTimer()
    {
        this.searchProgressTimer.Interval = 250;
        this.searchProgressTimer.Tick += new EventHandler(searchProgressTimer_Tick);
    }

    void searchProgressTimer_Tick(object sender, EventArgs e)
    {
        searchProgressBar.Increment(1);
        if (searchProgressBar.Value == searchProgressBar.Maximum)
            this.searchProgressTimer.Stop();
    }

    private void SearchDatabase_Click(object sender, EventArgs e)
    {
        this.searchProgressTimer.Start();

        // Time-consuming operation
        String filename = @"http://www.bankofengland.co.uk/publications/Documents/quarterlybulletin/qb0704.pdf";
        WebClient webClient = new WebClient();
        webClient.DownloadFileAsync(new Uri(filename), @"file.pdf");
        int test;
        for (int i = 0; i < 100000; i++)
            for (int j = 0; j < 100000; j++)
                test = i + j;


        this.searchProgressTimer.Stop();

    }
}
公共部分类表单1:表单
{
System.Windows.Forms.Timer;
公共表格1()
{
初始化组件();
this.searchProgressTimer=new System.Windows.Forms.Timer();
}
私有void初始化项()
{
this.searchProgressTimer.Interval=250;
this.searchProgressTimer.Tick+=新事件处理程序(searchProgressTimer\u Tick);
}
无效searchProgressTimer\u勾选(对象发送方,事件参数e)
{
搜索进度条增量(1);
if(searchProgressBar.Value==searchProgressBar.max)
this.searchProgressTimer.Stop();
}
私有无效搜索数据库\u单击(对象发送者,事件参数e)
{
this.searchProgressTimer.Start();
//耗时操作
字符串文件名=@“http://www.bankofengland.co.uk/publications/Documents/quarterlybulletin/qb0704.pdf";
WebClient WebClient=新的WebClient();
下载文件异步(新的Uri(文件名),@“file.pdf”);
智力测验;
对于(int i=0;i<100000;i++)
对于(int j=0;j<100000;j++)
试验=i+j;
this.searchProgressTimer.Stop();
}
}
(奇怪的是,这些函数被命名为tad,因为实际耗时的操作是数据库搜索,但该代码虽然工作正常,但非常长且复杂)


调试这段代码只是告诉我,
SearchButton\u Click
事件处理程序正确启动,但代码从未跳转到
searchProgressTimer\u勾选
事件处理程序。有什么想法吗?

你在这里做的有点让人困惑。假设你真的在某个地方初始化计时器-我想这就是正在发生的事情

Forms.Timer
类完全在窗体的消息循环上运行,因此当函数在该线程上运行时,它不能触发。因此,尽管您
Start()
计时器,但
Click()
函数与计时器在同一线程上运行,因此在该函数返回之前,计时器无法启动。但是,在该函数返回之前,请再次执行计时器

也许您想看看
线程.Timer
。尽管——理想情况下,您正在做的“工作”——无论是数据库操作还是简单的嵌套for循环——应该发生在不同的线程上,以便GUI的消息循环仍然可以处理

如果您确实为此生成了一个不同的线程,请不要忘记在主UI线程上调用任何UI更改或对UI元素的更改

调试这段代码只是告诉我SearchButton\u Click事件处理程序启动正确,但代码从未跳转到searchProgressTimer\u Tick事件处理程序

尝试将
initializetimer()
例程移动到窗体的构造函数中,因为看起来您从未连接计时器的勾号事件:

public Form1()
{
  InitializeComponent();
  this.searchProgressTimer = new System.Windows.Forms.Timer();
  this.searchProgressTimer.Interval = 250;
  this.searchProgressTimer.Tick += new EventHandler(searchProgressTimer_Tick);
}

这是因为GUI更新与数据库操作发生在同一线程中。数据库操作应该在另一个线程中完成,并调用GUI线程通知它更新。看看这个,因为它解释得相当好

所以1)我没有看到对InitializerItem()的调用


2)System.Windows.Forms.Timer在UI线程上引发其勾号事件。。与您正在执行耗时操作的线程完全相同。您需要偶尔将控制权让给消息泵一次,以便处理偶数。

我没有看到任何对InitializeTime()的调用在
searchProgressBar上放置断点。Incriment(1)
。您可以通过单击该行左侧的边距来执行此操作。将出现一个红点,让您知道断点在那里。在调试器中运行它,查看是否命中断点。如果在同一线程中执行时间密集型工作,则进度条将永远无法正常工作。后台工作人员是为这样的任务而设计的。这两个都是问题所在。我更新了代码,包括对
BackgroundWorker
及其功能的调用。我计划接受你的答案,但我是否应该编辑我的问题并添加有效的代码?将有效代码添加到问题中可以让未来的搜索者更快地获得答案。随你。