Извините за мой плохой английский. Надеюсь, кто-то предложит мне лучшую версию моего вопроса.
Я искал, но казалось, что не могу найти ответ на мою проблему.
В настоящее время я пишу приложение на C # WPF. Это приложение будет выполнять тяжелую задачу в течение длительного времени. Поэтому я решил создать другой класс с этим тяжелым методом и передать этот метод другому потоку. Я должен создать класс, чтобы сделать это, потому что тяжелый метод принимает параметры.
Я хочу приостановить и возобновить эту тему. Я знал, что должен использовать объект ManualResetEvent
или метод Thread.Sleep
.
После многих часов попыток и тестирования я запутался, почему я всегда заканчиваю тем, что приостанавливаю поток пользовательского интерфейса, но тяжелый поток все еще работает. То, что я пробовал, было:
Создайте ManualResetEvent
объект с именем mre
внутри HeavyClass
. Когда пользователь нажимает кнопку «Пауза», класс пользовательского интерфейса вызовет метод heavyClass.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();
}
}
Создайте метод с именем SleepThread
внутри HeavyClass
. Когда пользователь нажимает кнопку «Пауза», класс пользовательского интерфейса вызовет метод heavyClass.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();
}
}
Создайте EventHandler<MainWindow> PauseThread
внутри класса пользовательского интерфейса, затем напишите его дескриптор внутри HeavyClass
. Когда пользователь нажимает кнопку «Пауза», класс пользовательского интерфейса вызовет событие PauseThread(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
}
}
Как я уже говорил выше, я всегда приостанавливал поток пользовательского интерфейса, и тяжелая задача все еще выполняется.
И, наконец, в конце концов, я понял суть моей проблемы. То есть: какой поток вызывает Thread.Sleep () или WaitOne () будет заблокирован. Да, «какая нить», а не «какой класс».
Теперь все для меня имеет смысл. Но это не помогает мне достичь своей цели. И это заставляет меня думать, что я делаю, казалось бы, невозможную вещь. Ясно, что я хочу приостановить поток другим потоком. Но этот другой поток является тем, кто называет любые виды «приостановить поток», так что это тот, кто приостановлен. Я не имею ни малейшего представления о том, как сделать тяжелый метод сам по себе приостановленным. Он работает, как, черт возьми, он мог знать, когда пользователь нажимает кнопку Пауза?
Я в полной растерянности. Кто-то, пожалуйста, помогите мне заставить мое приложение работать как ожидалось.
Кстати, эта невозможная вещь заставляет меня думать, что я делаю вещи неправильно, не так ли?
ОБНОВЛЕНИЕ: Если вам нравится видеть мою тяжелую задачу, на самом деле это очень просто
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;
}
}