下面是一个具有'SomeMethod'方法的类,它说明了我的问题.
class SomeClass
{
AutoResetEvent theEvent = new AutoResetEvent(false);
// more member declarations
public void SomeMethod()
{
// some code
theEvent.WaitOne();
// more code
}
}
Run Code Online (Sandbox Code Playgroud)
该方法设计为线程安全的,并将在不同的线程中调用.现在我的问题是如何在任何时间点取消阻止在'theEvent'对象上调用'WaitOne'方法的所有线程?这个要求经常出现在我的设计中,因为我需要能够优雅地停止和启动我的多线程程序.在我看来,启动一个多线程程序相当简单,但很难阻止它.
这是我迄今为止尝试过的,显然有效.但这是标准方法吗?
public void UnblockAll()
{
do
{
theEvent.Set();
} while (theEvent.WaitOne(0));
}
Run Code Online (Sandbox Code Playgroud)
'UnblockAll'方法是'SomeClass'类的成员.此处使用的技术基于WaitOne方法的MSDN文档.我引用下面文档的相关部分:
如果millisecondsTimeout为零,则该方法不会阻止.它测试等待句柄的状态并立即返回.
在do..while循环中,我调用Set方法.这释放了一个可能由于调用WaitOne方法而被阻塞的线程(在'SomeMethod'方法中编码).接下来,我测试'theEvent'对象的状态,只是为了知道它是否有信号.此测试是通过调用带有超时参数的WaitOne方法的重载版本来完成的.我在调用WaitOne方法时使用的参数为零,根据文档结果,调用立即返回一个布尔值.如果返回值是true,那么"theEvent"的对象是信号状态中.如果在'SomeMethod'方法中对'WaitOne'方法的调用至少阻塞了一个线程,则调用'Set'方法(在'UnblockAll'方法中编码)将解除阻塞.因此,在'UnblockAll'方法中do..while语句结束时对'WaitOne'方法的调用将返回false.仅当没有线程被阻止时,返回值才为真.
上述推理是否正确,如果是正确的,该技术是否是处理我的问题的标准方法?我试图主要在.net compact-framework 2.0平台上使用该解决方案.
假设螺纹形成4个单独的螺纹并等待它们中的每一个直到它们完成.每个线程都会休眠一段时间,只有当共享的Mutex opbject没有被另一个线程占用时才会终止,然后通过它完成的事件发出信号(这是我的代码的简化版本,但在同一个地方失败)
但是,大多数情况下主线程将在WaitOne()中的一个看似随机等待.
此外,我不得不将我的代码的某些部分注释掉,因为它导致了更多的意外行为(也就是说,在每个线程完成主线程之后会以某种方式跳回到for子句并导致IndexOutOfBounds)
class Threading
{
static Mutex CM;
static List<Manga> SharedList;
static ManualResetEvent CEvent = new ManualResetEvent(false);
static ManualResetEvent Event1 = new ManualResetEvent(false);
static ManualResetEvent Event2 = new ManualResetEvent(false);
static ManualResetEvent Event3 = new ManualResetEvent(false);
static ManualResetEvent Event4 = new ManualResetEvent(false);
public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads)
{
CM = new Mutex(false);
SharedList = new List<Manga>();
ManualResetEvent[] evs = new ManualResetEvent[4];
evs[0] = Event1; // Event for t1
evs[1] = Event2; // Event for t2
evs[2] = Event3; // Event …Run Code Online (Sandbox Code Playgroud) 首先,我还是初学者,所以如果你有耐心,我会很感激:)
我今天一直在为此苦苦挣扎.
问题是,我想运行三个不同的背景工作者.但我想等到一个人完成下一个的运行,依此类推.
每个背景工作者都需要时间来完成.长话短说,问题是,我正在使用WaitOne(),所以每当前面的背景工作者告诉我它已经完成时,我就可以开始运行新的,但是UI线程一直在冻结,直到三个后台工作者完成.
我正在设置一个不同的AutoResetEvent,它是一个负责整个等待和运行的东西.
这是代码:
AutoResetEvent _resetRIEvent = new AutoResetEvent(false);
AutoResetEvent _resetHEvent = new AutoResetEvent(false);
AutoResetEvent _resetSEvent = new AutoResetEvent(false);
await Task.Run(() => bgwTestResInd.RunWorkerAsync());
_resetRIEvent.WaitOne();
await Task.Run(() => bgwTestHipot.RunWorkerAsync());
_resetHEvent.WaitOne();
await Task.Run(() => bgwTestSurge.RunWorkerAsync());
_resetSEvent.WaitOne();
MessageBox.Show("Im done for real.");
Run Code Online (Sandbox Code Playgroud)
此外,是否允许这样做?
private void bgwTestResInd_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetRIEvent.Set();
}
private void bgwTestHipot_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetHEvent.Set();
}
private void bgwTestSurge_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetSEvent.Set();
}
Run Code Online (Sandbox Code Playgroud) 我使用 ManualResetEnvent 来暂停/继续线程。代码示例如下。
private _rstEvent = new ManualResetEvent(true);
public void DoSomeWork()
{
while(judgementValue)
{
_rstEvent.WaitOne();
...
}
}
public void Pause()
{
_rstEvent.Reset();
}
public void Continue()
{
_rstEvent.Set();
}
Run Code Online (Sandbox Code Playgroud)
问题是,如果 while 循环很大怎么办,这意味着 while 语句中的每个循环都有很多操作要做。该线程将继续下去,直到遇到下一个_rstEvent.WaitOne();。除了已弃用的挂起之外,还有其他方法可以立即暂停线程吗?