2009-12-22 66 views
3

我有一个Windows窗体和一个类,它有两个以非确定的方式递归运行的简单方法(意思是不知道哪个递归会被调用,都可以调用另一个)。现在,递归期间有一些点我想暂停执行并等待用户点击“下一步”按钮。只有按下按钮后,递归函数才会继续。该类在单独的线程上运行,因此它不会阻止UI。如何使后台线程暂停,然后继续点击按钮?

在暂停期间,窗体只会从类中检索值并将其显示在列表框中。然后在按下按钮后,递归继续,直到下一个Pause()。我需要这个,所以用户可以一步一步看到递归中发生了什么。此外,我需要能够在递归方法(甚至多次)中的任何位置放置Pause(),而不会产生任何副作用...

我想到的唯一方法是调用Pause()方法一个循环检查一些锁定标志,然后睡眠一段时间(按钮会设置标志),但是我在Windows窗体中使用了Thread.Sleep()方法(锁定UI),所以我正在查看另一个选项。

有没有干净的方法来做到这一点?

回答

6

使用ManualResetEvent初始化为true,因此它开始设置。在一种方法或其他方法(或两者兼而有之)的着名地方,等待事件发生。大多数情况下,事件将被设置为后台线程会立即继续。但是,当用户单击暂停时,重置事件,导致后台线程在下一次到达事件时阻止。当用户下一次点击“恢复”时,设置了该事件,允许后台线程再次继续。

在这种情况下UI线程应该永远不会被阻塞。

+0

这有点修改,因为用户不会暂停,函数本身暂停。用户只执行该步骤。但是我已经把Reset()和WaitOne()放在我的Pause()中,然后在按钮上点击了我简单的Set()。它以满意的方式工作。这很有趣,我从来没有注意到这堂课。 – 2009-12-23 00:28:51

+0

这就是AutoResetEvent的工作原理。它会在线程成功等待时自动重置。 – 2009-12-23 00:33:44

+0

是的,AutoResetEvent也适用于我的场景,实际上使得代码更短(一行)。所以现在我只能在我的Pause()中调用WaitOne(),剩下的代码保持不变。 – 2009-12-23 08:08:22

2

使用AutoResetEvent对象。

从你的线程调用它的.WaitOne方法暂停它,并从你的按钮上调用它的.Set方法以取消暂停它。

+0

按预期在此方案中的'AutoResetEvent'将无法正常工作。 – 2009-12-22 23:50:18

+0

由于...在这种情况下不起作用吗? – 2009-12-23 00:16:39

+0

它的工作原理,所以没有,因为:) – 2009-12-23 08:08:57

1

这是一个以非标准方式使用互斥体的好地方。只要你的后台线程采取并释放Mutex,当它处于可以等待的位置时。

您的GUI线程在想要阻止后台线程时接受互斥锁,并在可以运行时释放它。

这种方式后台线程会在应该时候等待,并且在允许运行时简单地进出互斥量。

将“运行权”视为关键部分所保护的资源。

这样

// this object has to be visible to both threads 
System.Threading.Mutex mtx = new Mutex(); 

// worker thread does this wherever it's ok for it to pause 
mtx.WaitOne(); 
mtx.ReleaseMutex(); 

// main thread does this to pause the worker 
Mtx.WaitOne(); 

// main thread does this this to unpause it. 
mtx.ReleaseMutex(); 
相关问题