Need a timer that updates after each finish item in a Listbox
right now i have implemented a timer class like this.
static void DelaySec(string delayName)
{
switch (delayName)
{
case "Delay1":
System.Threading.Thread.Sleep(1000);
break;
case "Delay2":
System.Threading.Thread.Sleep(2000);
break;
case "Delay3":
System.Threading.Thread.Sleep(3000);
break;
case "Delay4":
S开发者_StackOverflowystem.Threading.Thread.Sleep(4000);
break;
case "Delay5":
System.Threading.Thread.Sleep(5000);
break;
default:
break;
}
}
i would like to set a delay and not a sleep between items in a listbox so my UI dont freeze.
hope someone out there who can help me.
If you're doing a significant amount of work - or even simulating it - you should not be doing it on the UI thread. That's why your UI thread is freezing.
You should be doing it on a background thread, and using Control.Invoke
/BeginInvoke
or possibly BackgroundWorker
to marshal any UI updates (e.g. changing a progress bar) back to the UI thread.
It's unclear what your timer is really meant to be doing here, but when you've worked out how to offload the work to a different thread, then describe what your code looks like.
Note that you could use System.Windows.Forms.Timer
to interact easily with the UI thread - but it should still be event-based, rather than you running a lot of work in the UI thread. So for example, you could create a "queue" of work to do (based on the listbox item), set up a timer to fire every second, and on each timer tick perform the work - if it's short - for that one item. Between calls, the UI thread will be free to update itself.
Note that the async feature of C# 5 will mean you will be able to write normal sequential code like this, but that's a way off yet.
...
stopwatch.Start();
timerLabel.Visible = true;
progressBar1.Maximum = SequenceListBox.Items.Count;
progressBar1.Step = (progressBar1.Maximum / SequenceListBox.Items.Count);
progressBar1.PerformStep();
foreach(ElementControl item in SequenceListBox.Items)
{
item.RunElement();
Application.DoEvents();
}
stopwatch.Stop();
...
I think this is what you want to achieve. However, I am not sure whether when the stopwatch to start and stop timing. Your example seems to be start the watch multiple times and stop it only once.
private int currItem;
private List<ElementControl> Elements = new List<ElementControl>();
private void StartButton_Click(object sender, EventArgs e)
{
if (SequenceListBox.Items.Count <= 0)
{
MessageBox.Show("Please select an Item");
return;
}
// Prevent starting again
StartButton.Enabled = false;
Elements.Clear();
foreach (ElementControl ele in SequenceListBox.Items)
Elements.Add(ele);
// Must start stopwatch before timer to prevent timer_Elapsed from closing a non-existent stopwatch
stopwatch = Stopwatch.StartNew();
stopwatch.Start();
// Start timer
System.Timers.Timer timer = new System.Timers.Timer(1000);
timer.AutoReset = true;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
public delegate void ReportProgressHandler(int value, string text);
private void ReportProgress(int value, string text)
{
if (InvokeRequired)
Invoke(new ReportProgressHandler(ReportProgress), value, text);
else
{
if(value <= progressBar1.Maximum)
progressBar1.Value = value;
timerLabel.Text = text;
}
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// If all item process, stop timer, stopwatch and re-enable button
if (currItem >= Elements.Count)
{
timer.Stop();
stopwatch.Stop();
ReportProgress (curItem, stopwatch.Elapsed.TotalSeconds.ToString("0" + " sec"));
stopwatch = null;
MessageBox.Show("The Test is Finish");
//StartButton.Enabled = true;
// Use the same approach as that used to report progress.
}
else
{
// Select item and run it
ElementControl item = Elements[curItem];
item.RunElement();
currItem++;
ReportProgress (curItem, "sometext"));
}
}
this is another possible way to do it:
class Task
{
public List<ElementControl> Elements = new List<ElementControl>();
}
private void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
Task task = new Task();
foreach (ElementControl ele in SequenceListBox.Items)
task.Elements.Add(ele);
progressBar1.Maximum = task.Elements.Count;
backgroundWorker1.RunWorkerAsync(task);
}
public delegate void ReportProgressHandler(int value, string text);
private void ReportProgress(int value, string text)
{
if (InvokeRequired)
Invoke(new ReportProgressHandler(ReportProgress), value, text);
else
{
if(value <= progressBar1.Maximum)
progressBar1.Value = value;
label1.Text = text;
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Task task = e.Argument as Task;
if (task != null)
{
int i = 0;
foreach (ElementControl ele in task.Elements)
{
i++;
ele.RunElement();
ReportProgress(i, "sometext + " + i.ToString());
System.Threading.Thread.Sleep(1000);
}
MessageBox.Show("Completed!");
}
}
精彩评论