Sorry for my bad English. Hope someone suggests me a better version of my question.
I've searched but seemed like I couldn't find the answer for my problem.
Currently, I'm writing a C# WPF app. This app will perform a heavy task in a long time. So I've decided to create another class with that heavy method and pass that method to another thread. I have to create a class to do that because the heavy method takes parameters.
I want the ability to suspend and resume that thread. I've known that I should use a ManualResetEvent
object or Thread.Sleep
method.
After many hours of trying and testing, getting confused why I always end up suspend the UI thread but the heavy thread is still running. What I've tried were:
Create a
ManualResetEvent
object calledmre
inside theHeavyClass
. When user click the Pause button, the UI class will call the methodheavyClass.mre.WaitOne()
.class HeavyClass { // properties ManualResetEvent mre = new ManualResetEvent(false); public void HeavyRun() { //Do something takes really long time //And doesn't have any loops } } class MainWindow : Window { // properties private HeavyClass heavyClass = new HeavyClass(); private void buttonStart_Click(object sender, RoutedEventArgs e) { Thread t = new Thread(heavyClass.HeavyRun); t.Start(); } private void buttonPause_Click(object sender, RoutedEventArgs e) { heavyClass.mre.WaitOne(); } }
Create a method called
SleepThread
inside theHeavyClass
. When user click the Pause button, the UI class will call the methodheavyClass.SleepThread()
.class HeavyClass { //properties ManualResetEvent mre = new ManualResetEvent(false); public void SleepThread() { Thread.Sleep(Timeout.Infinite); //mre.WaitOne(); //They are the same behavior } public void HeavyRun() { //Do something takes really long time //And doesn't have any loops } } class MainWindow : Window { // properties private HeavyClass heavyClass = new HeavyClass(); private void buttonStart_Click(object sender, RoutedEventArgs e) { Thread t = new Thread(heavyClass.HeavyRun); t.Start(); } private void buttonPause_Click(object sender, RoutedEventArgs e) { heavyClass.SleepThread(); } }
Create an
EventHandler<MainWindow> PauseThread
inside the UI class, then write its handle inside theHeavyClass
. When user click the Pause button, the UI class will trigger the eventPauseThread(this, this)
.class MainWindow : Window { // properties private HeavyClass heavyClass = new HeavyClass(); public event EventHandler<MainWindow> PauseThread; private void buttonStart_Click(object sender, RoutedEventArgs e) { Thread t = new Thread(heavyClass.HeavyRun); t.Start(); } private void buttonPause_Click(object sender, RoutedEventArgs e) { PauseThread(this, this); } } class HeavyClass { // properties ManualResetEvent mre = new ManualResetEvent(false); public void HeavyRun() { MainWindow.PauseThread += (s, E) => { Thread.Sleep(Timeout.Infinite); //mre.WaitOne(); //They are the same behavior }; //Do something takes really long time //And doesn't have any loops } }
As I said above, I always paused the UI thread and the heavy task is still running.
And finally in the end, I've known the essence of my problem. That is: which thread calls Thread.Sleep() or WaitOne() will be blocked. Yeah, "which thread", not "which class".
Everything makes sense for me now. But that doesn't help me to achieve my goal. And that leads me to think that I am doing the seemingly impossible thing. It's clearly that I want to pause a thread by another thread. But that another thread is the one who calls any kinds of "suspend thread", so it is the one who is suspended. I don't have any idea about how to make the heavy method to be suspended by itself. It is running, how the hell it could know when the user click the Pause button?
I am at a total loss. Someone please help me to make my app works as expected.
By the way, this impossible thing makes me think that I am doing things wrong way, is it?
UPDATE: If you like to see my heavy task, actually it is very simple
class HeavyClass
{
public string filePath = "D:\\Desktop\\bigfile.iso";//This file is about 10GB
public string HeavyRun()
{
string MD5Hash;
MD5 md5 = MD5.Create();
Stream stream = File.OpenRead(filePath);
MD5Hash = Encoding.Default.GetString(md5.ComputeHash(stream));
return MD5Hash;
}
}