如何在 .NET 3.5 中实现 .NET 4 功能的 Barrier 类
由于某些原因,我必须坚持使用 .NET 3.5,并且我需要 .NET 4 中的 Barrier 类的功能。我有一堆线程来做一些工作,我希望它们互相等待,直到所有工作都完成。当一切完成后,我希望他们以类似的方式一次又一次地完成这项工作。 受到线程之间的差异的鼓励C# 4.0 中的 Barrier 和 C# 3.0 中的 WaitHandle? 我决定使用 AutoResetEvent 和 WaitHandle 类来实现 Barrier 功能。 尽管我的代码遇到了问题:
class Program
{
const int numOfThreads = 3;
static AutoResetEvent[] barrier = new AutoResetEvent[numOfThreads];
static Random random = new Random(System.DateTime.Now.Millisecond);
static void barriers2(object barrierObj)
{
AutoResetEvent[] barrierLocal = (AutoResetEvent[])barrierObj;
string name = Thread.CurrentThread.Name;
for (int i = 0; i < 10; i++)
{
int sleepTime = random.Next(2000, 10000);
System.Console.Out.WriteLine("Thread {0} at the 'barrier' will sleep for {1}.", name, sleepTime);
Thread.Sleep(sleepTime);
System.Console.Out.WriteLine("Thread {0} at the 'barrier' with time {1}.", name, sleepTime);
int currentId = Convert.ToInt32(name);
//for(int z = 0; z < numOfThreads; z++)
barrierLocal[currentId].Set();
WaitHandle.WaitAll(barrier);
/*
for (int k = 0; k < numOfThreads; k++)
{
if (k == currentId)
{
continue;
}
System.Console.Out.WriteLine("Thread {0} is about to wait for the singla from thread: {1}", name, k);
barrierLocal[k].WaitOne();
System.Console.Out.WriteLine("Thread {0} is about to wait for the singla from thread: {1}. done", name, k);
}
*/
}
}
static void Main(string[] args)
{
for (int i = 0; i < numOfThreads; i++)
{
barrier[i] = new AutoResetEvent(false);
}
for (int i = 0; i < numOfThreads; i++)
{
Thread t = new Thread(Program.barriers2);
t.Name = Convert.ToString(i);
t.Start(barrier);
}
}
}
我收到的输出如下:
Thread 0 at the 'barrier' will sleep for 7564 “屏障”处的线程 1 将休眠 5123 “屏障”处的线程 2 将休眠 4237 线程 2 位于“屏障”,时间为 4237 线程 1 位于“障碍”处,时间为 5123 线程 0 位于“屏障”,时间为 7564 “屏障”处的线程 0 将休眠 8641 线程 0 在“障碍”处,时间为 8641
就是这样。最后一行之后不再有输出,应用程序也不会终止。看起来好像存在某种僵局。然而找不到问题所在。欢迎任何帮助。
谢谢!
For some reasons I have to stick to .NET 3.5 and I need a functionality of Barrier class from .NET 4. I have a bunch of threads that do some work and I want them to wait for each other until all are done. When all are done I want that they do the job again and again in the similar manner.
Encouraged by the thread Difference between Barrier in C# 4.0 and WaitHandle in C# 3.0? I have decided to implement the Barrier functionality with AutoResetEvent and WaitHandle classes.
Altough I encounter a problem with my code:
class Program
{
const int numOfThreads = 3;
static AutoResetEvent[] barrier = new AutoResetEvent[numOfThreads];
static Random random = new Random(System.DateTime.Now.Millisecond);
static void barriers2(object barrierObj)
{
AutoResetEvent[] barrierLocal = (AutoResetEvent[])barrierObj;
string name = Thread.CurrentThread.Name;
for (int i = 0; i < 10; i++)
{
int sleepTime = random.Next(2000, 10000);
System.Console.Out.WriteLine("Thread {0} at the 'barrier' will sleep for {1}.", name, sleepTime);
Thread.Sleep(sleepTime);
System.Console.Out.WriteLine("Thread {0} at the 'barrier' with time {1}.", name, sleepTime);
int currentId = Convert.ToInt32(name);
//for(int z = 0; z < numOfThreads; z++)
barrierLocal[currentId].Set();
WaitHandle.WaitAll(barrier);
/*
for (int k = 0; k < numOfThreads; k++)
{
if (k == currentId)
{
continue;
}
System.Console.Out.WriteLine("Thread {0} is about to wait for the singla from thread: {1}", name, k);
barrierLocal[k].WaitOne();
System.Console.Out.WriteLine("Thread {0} is about to wait for the singla from thread: {1}. done", name, k);
}
*/
}
}
static void Main(string[] args)
{
for (int i = 0; i < numOfThreads; i++)
{
barrier[i] = new AutoResetEvent(false);
}
for (int i = 0; i < numOfThreads; i++)
{
Thread t = new Thread(Program.barriers2);
t.Name = Convert.ToString(i);
t.Start(barrier);
}
}
}
The output I receive is as follows:
Thread 0 at the 'barrier' will sleep for 7564
Thread 1 at the 'barrier' will sleep for 5123
Thread 2 at the 'barrier' will sleep for 4237
Thread 2 at the 'barrier' with time 4237
Thread 1 at the 'barrier' with time 5123
Thread 0 at the 'barrier' with time 7564
Thread 0 at the 'barrier' will sleep for 8641
Thread 0 at the 'barrier' with time 8641
And that's it. After the last line there is no more output and the app does not terminate. It looks like there is some sort of deadlock. However can not find the issue. Any help welcome.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
那是因为您使用了 AutoResetEvent。其中一个线程的 WaitAll() 调用将首先完成。这会自动导致所有 ARE 上的 Reset()。这会阻止其他线程完成其 WaitAll() 调用。
这里需要一个ManualResetEvent。
That's because you use AutoResetEvent. One of the thread's WaitAll() call is going to complete first. Which automatically causes Reset() on all the AREs. Which prevents the other threads from ever completing their WaitAll() calls.
A ManualResetEvent is required here.
下载 .NET 3.5 的反应式扩展向后移植。您将发现 Barrier 类以及 .NET 4.0 中发布的其他有用的并发数据结构和同步机制。
Download the Reactive Extensions backport for .NET 3.5. You will find the
Barrier
class along with the other useful concurrent data structures and synchronization mechanisms that were released in .NET 4.0.这是我用于 XNA 游戏 的实现。当我写这篇文章时,Barrier 还不可用,我仍然坚持使用 .Net 3.5。它需要三组ManualResetEvents,以及一个计数器数组来保持相位。
设置线程门:
线程工作者方法:
Here is my implementation I use for my XNA game. Barrier was not available when I wrote this, and I am still stuck with .Net 3.5. It requires three sets of ManualResetEvents, and a counter array to keep phase.
Setting up the thread gate:
Thread worker method: