我建议使用ThreadPool之类的东西,但是如果您想使用手动创建的前台线程,并且希望它们按照您演示的顺序启动-这是解决方案(这似乎有些棘手):
主要表演者:
ManualResetEventSlim-表示线程同步事件,该事件在发出信号时必须手动重置。这是不切换上下文的最佳同步工具之一。但是请确保不要将其与长期阻塞一起使用,因为它会旋转,并且如果花费的时间比预期的长,请采取常规事件句柄等待!
Interlocked-为多个线程共享的变量提供原子操作。
代码:
class Program
{
static ManualResetEventSlim mres = new ManualResetEventSlim(false);
static int x = 89;
static Thread p0 = new Thread(P0);
static Thread p1 = new Thread(P1);
static void P0()
{
Interlocked.Increment(ref x);
Console.WriteLine(x);
}
static void P1()
{
while(true)
{
if (p0.ThreadState == ThreadState.Unstarted)
mres.Wait();
else
break;
}
p0.Join();
Interlocked.Decrement(ref x);
Console.WriteLine(x);
}
static void Main(string[] args)
{
p1.Start();
p0.Start();
mres.Set(); // This will "kick off" the mres spinning inside P1
mres.Dispose();
Console.ReadKey();
}
}
旁注
请勿使用锁定操作符或监控器,除非您100%确定阻止不会持续很长时间。这些是混合同步结构,可能会切换执行上下文,这对性能不是很好。同样,即使您在锁运算符中遇到异常,它也仍将“取消阻止”线程,因为它在try / finally中转换并在幕后的finally块中使用Monitor.Exit。因此,下一个线程可能会访问损坏的数据。
使用监控器,当您知道锁将持续很长时间或不确定时。因为它将最终阻塞您的线程,并且不会出现活锁或持续滚动。
,
如注释中所述,更改任务开始的顺序。另外,值得在启动p1之前检查p0是否正在运行:
static void Main(string[] args)
{
p0.Start();
if (p0.ThreadState == ThreadState.Running)
p1.Start();
Console.ReadKey();
}
本文链接:https://www.f2er.com/2961281.html