我写了一个小程序,打印“x”,然后是“+”,然后是“x”,依此类推。
我的想法是让它在两个线程中运行,以便第一个线程打印“x”,第二个线程打印“+”。输出如下所示:
“x” - >线程号1
“+” - >线程号2
“x” - >主题1 enter code here
“+” - >线程号2
等等..
我写的内容似乎工作正常,但在我看来它是写的 非常老套的方式:
public class Example
{
private static int count = 10;
private static int i = 0;
private static bool isOneActive = false;
private static void Run1(object o)
{
string s = o as string;
while(true)
{
if (!isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = true;
if (i++ > count) break;
}
}
}
private static void Run2(object o)
{
string s = o as string;
while(true)
{
if (isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = false;
if (i++ > count) break;
}
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
我知道现在.NET有许多用于线程同步的工具,例如ManualResetEvent类和Task库。那么我们如何使用ManualResetEvent类编写相同的程序呢?它有可能吗?
答案 0 :(得分:4)
您的代码不仅仅是老式的,效率非常低。它无缘无故地旋转,只能等待;这应称为Busy wait应该尽可能避免。
更好的方法是使用评论中提到的Waithandles。
一个简单的实现,代码变化很小,如下所示。
public class Example
{
private static int count = 10;
private static int i = 0;
private static AutoResetEvent firstEvent = new AutoResetEvent(true);
private static AutoResetEvent secondEvent = new AutoResetEvent(false);
private static void Run1(object o)
{
string s = o as string;
while (true)
{
firstEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
secondEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
private static void Run2(object o)
{
string s = o as string;
while (true)
{
secondEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
firstEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
}
请注意firstEvent
是在初始状态标志设置为true
的情况下实例化的,这意味着第一个线程最初不会等待。
答案 1 :(得分:3)
考虑这个例子(fiddle):
static void Main(string[] args)
{
var console = new object();
int i = 0;
Task.Run(() =>
{
lock (console)
while (i++ < 10)
{
Console.Write(i);
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Task.Run(() =>
{
lock (console)
while (i < 10)
{
Console.Write('+');
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
}