Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
线程C#的问题,随机给出一个错误,表示进程未启动_C#_.net_Multithreading_Console_Race Condition - Fatal编程技术网

线程C#的问题,随机给出一个错误,表示进程未启动

线程C#的问题,随机给出一个错误,表示进程未启动,c#,.net,multithreading,console,race-condition,C#,.net,Multithreading,Console,Race Condition,线程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() {

线程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之类的工具,但是如果您想使用手动创建的前台线程,并且希望它们按照您演示的顺序开始-下面是解决方案(这可能看起来有点棘手):

主要执行者:

-表示线程同步事件,当发出信号时,必须手动重置该事件。这是最好的同步工具之一,不会切换上下文。但请确保不要将其用于长期阻塞,因为它会旋转,并且如果所需时间比预期的要长,请求助于常规事件句柄等待

-为多个线程共享的变量提供原子操作

代码:

    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%确定封锁不会持续很长时间时,不要使用锁定操作员或监视器。这些是混合同步结构,可能会切换执行上下文,这对性能不是很好。此外,即使在lock操作符中出现异常,它也会在try/finally中转换线程并在引擎盖下的finally块中使用Monitor.Exit时“解除阻止”线程。因此,下一个线程可能会访问损坏的数据


当您知道您的锁会持续很长时间或您不确定时,请使用监视器。因为它最终会阻塞你的线程,不会出现死锁或持续滚动。

好吧,你在
p0
之前开始
p1
,为比赛的最坏结果创造了良好的条件。你在
p1
之后开始
p0
,因此,当
p0
尚未运行时,可以执行
Join
。您还可以修改共享资源
x
,而不使用锁语句或互锁API。另外,为了你未来同事的爱,请不要把英语和意大利语混在一起。