I have a trackbar in my WinForms program which by moving it a huge and time consuming method will be refreshed. Have a look at this code:
trackBar_ValueChanged(object sender, EventArgs e)
{
this.RefreshData();
}
This track bar has 20 steps. If user grab the trackbar's slider and pull it from 20 to 0 in my case, 'RefreshData' will be executed 20 times although it shows correct data when it ends the process that is 'RefreshData' with value 0, I want to do something like it only calls the 'RefreshData' when the trackBar slider has been released so it wont process all the steps to the releasing point on the track bar.
Any help and tips to achieve this would be appericiated! Thanks.
The way that I've done this sort of thing before is to use a timer. Every time the value of the TrackBar changes, reset the timer so that it fires in 500ms (or whatever is appropriate for you). If the user changes the value before the timer fires, it will be reset again, meaning that even if it changes multiple times, the timer will only fire once.
The only thing to watch here is that the timer will fire on a different thread and you won't be able to update the UI from that thread, so you'll have to invoke back onto the UI thread to make changes there. That said, however, if you can move the majority of your expensive work onto this background thread, you'll keep the UI responsive for longer.
Here's some sample code that should give you some idea of what I mean.
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));
}
}
Edit: Here's a solution that uses a win forms timer to do the timings. The difference here is that you'll lock the UI up while the calculation is running; this may or may not be ok in your situation.
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();
}
}