3

我的 WinForms 程序中有一个跟踪栏,通过移动它会刷新一个巨大且耗时的方法。看看这段代码:

trackBar_ValueChanged(object sender, EventArgs e)
{
     this.RefreshData();
}

这个轨迹栏有 20 个步骤。如果用户抓住轨迹栏的滑块并将其从 20 拉到 0 在我的情况下,“RefreshData”将被执行 20 次,尽管它在结束值为 0 的“RefreshData”进程时显示正确的数据,我想做类似的事情它只在 trackBar 滑块被释放时调用“RefreshData”,因此它不会处理所有步骤到轨道栏上的释放点。

实现这一目标的任何帮助和提示都将得到满足!谢谢。

4

4 回答 4

5

怎么样:

Boolean user_done_updating = false;

private void MytrackBar_ValueChanged(object sender, EventArgs e)
{
    user_done_updating = true;
}

private void MytrackBar_MouseUp(object sender, MouseEventArgs e)
{
    if (user_done_updating)
    {
        user_done_updating = false;
        //Do Stuff
    }
}
于 2012-07-26T14:19:50.897 回答
2

我以前做过这种事情的方法是使用计时器。每次 TrackBar 的值发生变化时,重置计时器,使其在 500 毫秒内触发(或任何适合您的时间)。如果用户在定时器触发之前改变了值,它会再次被重置,这意味着即使它改变了多次,定时器也只会触发一次。

这里唯一要注意的是计时器将在不同的线程上触发,您将无法从该线程更新 UI,因此您必须调用回 UI 线程以在那里进行更改。尽管如此,如果您可以将大部分昂贵的工作转移到这个后台线程上,您将保持 UI 响应更长时间。

这是一些示例代码,可以让您了解我的意思。

public partial class Form1 : Form
{
    private int updateCount;
    private System.Threading.Timer timer;

    public Form1()
    {
        this.InitializeComponent();
        this.timer = new System.Threading.Timer(this.UpdateValue);
    }

    private void UpdateValue(object state)
    {
        // Prevent the user from changing the value while we're doing
        // our expensive operation
        this.Invoke(new MethodInvoker(() => this.trackBar1.Enabled = false));

        // Do the expensive updates - this is still on a background thread
        this.updateCount++;

        this.Invoke(new MethodInvoker(this.UpdateUI));
    }

    private void UpdateUI()
    {
        this.label1.Text = this.updateCount.ToString();

        // Re-enable the track bar again
        this.trackBar1.Enabled = true;
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Change(TimeSpan.FromMilliseconds(500), new TimeSpan(-1));
    }
}

编辑:这是一个使用赢表计时器来计时的解决方案。此处的区别在于您将在计算运行时锁定 UI;在您的情况下,这可能会也可能不会。

public partial class Form1 : Form
{
    private int updateCount;
    private Timer timer;

    public Form1()
    {
        this.InitializeComponent();

        this.timer = new Timer();
        this.timer.Interval = 500;
        this.timer.Tick += this.Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        this.timer.Stop();

        this.updateCount++;
        this.label1.Text = this.updateCount.ToString();
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Stop();
        this.timer.Start();
    }
}
于 2011-04-19T20:11:40.977 回答
1

考虑在新线程中执行长时间运行的方法。维护对该线程的引用并在重新启动它之前调用 Thread.Abort()。

于 2012-07-26T14:35:51.120 回答
0

尝试KeyUp事件:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keyup.aspx

于 2011-04-19T14:29:32.157 回答