Answered by:
Best way to pause and resume a thread
Question
-
What could be the best way to pause and resume a thread. Actually I was working on an application where in on click event of "START COPY" button I am spawning a thread which starts copying all the files of a source dir to a destination directory. However I wanted a flexibility to pause the copy process when ever I click on "PAUSE COPY" button, which inturn should change the label of "PAUSE COPY" to "RESUME COPY". When I click on "RESUME COPY" button, the copy process which was paused earlier should get resumed.
I kind of achived this functionality using Thread.Suspend and Thread.Resume methods but lated found that these are depricated. So what couldbe the best way to achive this?
Answers
-
Hi,
Thanks for your post.
I done it by a flag named 'copyStatus' as below:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace WindowsFormsApplication1 { public class Form1 : Form { Button btn = new Button() { AutoSize = true, Text = "START COPY" }; enum COPY_STATUS { NOT_STARTED, RUNNING, PAUSED, FINISHED }; COPY_STATUS copyStatus = COPY_STATUS.NOT_STARTED; Thread copyThread; public Form1() { this.StartPosition = FormStartPosition.CenterScreen; btn.Click += new EventHandler(btn_Click); this.Controls.Add(btn); copyThread = new Thread(copyThreadMethod); this.FormClosed += new FormClosedEventHandler(Form1_FormClosed); } void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (copyStatus == COPY_STATUS.RUNNING || copyStatus == COPY_STATUS.PAUSED) copyThread.Abort(); } void copyThreadMethod() { ProgressBar pb = new ProgressBar(); Form f = new Form() { Text = "copying...", ClientSize = pb.Size, TopMost = true,StartPosition= FormStartPosition.CenterScreen }; f.FormClosing += new FormClosingEventHandler(f_FormClosing); f.Controls.Add(pb); f.Show(); while (pb.Value < 100) { while (copyStatus != COPY_STATUS.RUNNING) Application.DoEvents();//wait Thread.Sleep(200);//file copying simulation pb.Value++; Application.DoEvents(); } copyStatus = COPY_STATUS.FINISHED; } void f_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = copyStatus == COPY_STATUS.RUNNING || copyStatus == COPY_STATUS.PAUSED; } void btn_Click(object sender, EventArgs e) { switch (copyStatus) { case COPY_STATUS.NOT_STARTED: copyThread.Start(); copyStatus = COPY_STATUS.RUNNING; btn.Text = "PAUSE COPY"; break; case COPY_STATUS.RUNNING: copyStatus = COPY_STATUS.PAUSED; btn.Text = "RESUME COPY"; break; case COPY_STATUS.PAUSED: copyStatus = COPY_STATUS.RUNNING; btn.Text = "PAUSE COPY"; break; } } } }Best regards,
Yasser
LEARN HOW WPF IS FLEXIBLE IN PRESENTATION DURING A QUICK SIMPLE WALKTHROUGH:
Walkthrough: Displaying multi column ComboBox by using Windows Presentation Foundation (WPF) data templating- Marked as answer by Liliane Teng Wednesday, June 9, 2010 6:47 AM
All replies
-
-
Hi,
Thanks for your post.
I done it by a flag named 'copyStatus' as below:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace WindowsFormsApplication1 { public class Form1 : Form { Button btn = new Button() { AutoSize = true, Text = "START COPY" }; enum COPY_STATUS { NOT_STARTED, RUNNING, PAUSED, FINISHED }; COPY_STATUS copyStatus = COPY_STATUS.NOT_STARTED; Thread copyThread; public Form1() { this.StartPosition = FormStartPosition.CenterScreen; btn.Click += new EventHandler(btn_Click); this.Controls.Add(btn); copyThread = new Thread(copyThreadMethod); this.FormClosed += new FormClosedEventHandler(Form1_FormClosed); } void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (copyStatus == COPY_STATUS.RUNNING || copyStatus == COPY_STATUS.PAUSED) copyThread.Abort(); } void copyThreadMethod() { ProgressBar pb = new ProgressBar(); Form f = new Form() { Text = "copying...", ClientSize = pb.Size, TopMost = true,StartPosition= FormStartPosition.CenterScreen }; f.FormClosing += new FormClosingEventHandler(f_FormClosing); f.Controls.Add(pb); f.Show(); while (pb.Value < 100) { while (copyStatus != COPY_STATUS.RUNNING) Application.DoEvents();//wait Thread.Sleep(200);//file copying simulation pb.Value++; Application.DoEvents(); } copyStatus = COPY_STATUS.FINISHED; } void f_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = copyStatus == COPY_STATUS.RUNNING || copyStatus == COPY_STATUS.PAUSED; } void btn_Click(object sender, EventArgs e) { switch (copyStatus) { case COPY_STATUS.NOT_STARTED: copyThread.Start(); copyStatus = COPY_STATUS.RUNNING; btn.Text = "PAUSE COPY"; break; case COPY_STATUS.RUNNING: copyStatus = COPY_STATUS.PAUSED; btn.Text = "RESUME COPY"; break; case COPY_STATUS.PAUSED: copyStatus = COPY_STATUS.RUNNING; btn.Text = "PAUSE COPY"; break; } } } }Best regards,
Yasser
LEARN HOW WPF IS FLEXIBLE IN PRESENTATION DURING A QUICK SIMPLE WALKTHROUGH:
Walkthrough: Displaying multi column ComboBox by using Windows Presentation Foundation (WPF) data templating- Marked as answer by Liliane Teng Wednesday, June 9, 2010 6:47 AM
-
Thread.Sleep is as good as any. See "Pausing and Resuming Threads" in help.
I think sleeping isn't good idea during copying one file, however it's good to sleeping between copying two files. I mean that it's better to have an atomic copy for one file.
LEARN HOW WPF IS FLEXIBLE IN PRESENTATION DURING A QUICK SIMPLE WALKTHROUGH:
Walkthrough: Displaying multi column ComboBox by using Windows Presentation Foundation (WPF) data templating -
Collegues already pointed you in the right direction with their posts. I just add some spice to the cooking.
I'd personally prefer to add the objects to be elaborated (entire files, filenames, paths, whatever) in a Queue and let the thread Dequeue. In this way you have a single and easily programmable channel of input to the thread, completely decoupled from external world. Then you can pause the reading from the queue by setting a property in the class, like a "Boolean IsAllowedToProcessData" that you control from external.
In the external thread loop put a Boolean IsAllowedToRun that you can set to false making the thread end. In the same way, in an internal loop, the check is made on the IsAllowedToProcessData that if false simply skips the { block where operations are made } but still making some Thread.Sleep.
Something like
while (IsAllowedToRun) {
if(IsAllowedToProcessData && myQueue.Count>0) { some calculations }
else Thread.Sleep(100) }
}Giuseppe