线程 C# 的问题,随机给出一个错误,它表示进程未启动
Problem with thread C#, randomly gives an error in which it says that the process is not started
线程 C# 出现问题,随机给出一个错误,其中指出进程“0”未启动。
错误发生在 p0.Join
namespace ThreadEsercitazione
{
class Program
{
static int x = 89;
static Thread p0 = new Thread(P0);
static Thread p1 = new Thread(P1);
static void P0()
{
x++;
Console.WriteLine(x);
}
static void P1()
{
p0.Join(); //(Thread is not started)
x--;
Console.WriteLine(x);
}
static void Main(string[] args)
{
p1.Start();
p0.Start();
Console.ReadKey();
}
}
}
如评论所述,更改任务启动顺序。此外,在启动 p1:
之前检查 p0 是否为 运行 是值得的
static void Main(string[] args)
{
p0.Start();
if (p0.ThreadState == ThreadState.Running)
p1.Start();
Console.ReadKey();
}
我建议使用 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% 确定您的封锁不会持续很长时间时,请不要使用 锁定操作员或监视器。这些是混合同步结构,可能会切换执行上下文,这对性能来说不是很好。此外,即使您在锁定运算符中遇到异常,它仍然会 "unblock" 您的线程,因为它在 try / finally 中进行翻译,并在引擎盖下的 finally 块中使用 Monitor.Exit 。因此下一个线程可能会访问损坏的数据。
使用 监控何时知道您的锁会持续很长时间或不确定。因为它最终会阻塞你的线程并且不会有活锁或持续滚动。
线程 C# 出现问题,随机给出一个错误,其中指出进程“0”未启动。 错误发生在 p0.Join
namespace ThreadEsercitazione
{
class Program
{
static int x = 89;
static Thread p0 = new Thread(P0);
static Thread p1 = new Thread(P1);
static void P0()
{
x++;
Console.WriteLine(x);
}
static void P1()
{
p0.Join(); //(Thread is not started)
x--;
Console.WriteLine(x);
}
static void Main(string[] args)
{
p1.Start();
p0.Start();
Console.ReadKey();
}
}
}
如评论所述,更改任务启动顺序。此外,在启动 p1:
之前检查 p0 是否为 运行 是值得的static void Main(string[] args)
{
p0.Start();
if (p0.ThreadState == ThreadState.Running)
p1.Start();
Console.ReadKey();
}
我建议使用 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% 确定您的封锁不会持续很长时间时,请不要使用 锁定操作员或监视器。这些是混合同步结构,可能会切换执行上下文,这对性能来说不是很好。此外,即使您在锁定运算符中遇到异常,它仍然会 "unblock" 您的线程,因为它在 try / finally 中进行翻译,并在引擎盖下的 finally 块中使用 Monitor.Exit 。因此下一个线程可能会访问损坏的数据。
使用 监控何时知道您的锁会持续很长时间或不确定。因为它最终会阻塞你的线程并且不会有活锁或持续滚动。