当前位置:编程学习 > C#/ASP.NET >>

【100分】C#进程的怪事

C#进程的怪事
【希望大家在仔细思考并亲自测试后再行回帖】
我写了3个程序:p1,p2,p3
p1:
        private void Form1_Load(object sender, EventArgs e)
        {
            while (true)
            {
                System.Threading.Thread.Sleep(5000);
                while (Process.GetProcessesByName("p2").Length > 0) ;
                Process.Start("p2");
            }
        }
p2:
        private void Form1_Load(object sender, EventArgs e)
        {
            while (true)
            {
                System.Threading.Thread.Sleep(5000);
                while (Process.GetProcessesByName("p1").Length > 0) ;
                Process.Start("p1");
            }
        }
p3:
        private void button1_Click(object sender, EventArgs e)
        {
            Process.GetProcessesByName("p1")[0].Kill();
            System.Threading.Thread.Sleep(5000);
            Process.GetProcessesByName("p2")[0].Kill();
            MessageBox.Show("OK");
        }

p1,p2实际上是进程双保险,用任务管理器是结束不了的,因为你结束其中一个,另一个就会马上启动它。
p3是用于结束这两个进程的,但我发现了严重的问题:
【如果注释掉这3个程序的延时语句,甚至在p3中设置一个小延时(如300毫秒),p3可以成功的结束p1,p2】(例一)
【如果加上延时语句,甚至把p3的延时缩短到300毫秒(p1,p2仍是5000毫秒),p3竟无法结束p1,p2】(例一中p3的延时大于p1,p2,尚且能够成功,这里p3的延时小于p1,p2,竟然还不能成功了,结论完全相反!!!)
太不可思议了!!!

当然,可能有这样一个解释(这里p3延时为300毫秒):
当p3结束p1时,p2据上次延时已超过4700毫秒,所以它能赶在300毫秒(到时它本身会被结束)之内启动p1
但如果是这样,p3不能结束p1,p2的概率只有6%(300/5000),但经过我的测试,p3不能结束p1,p2的概率超过95%!!!
当然,概率可能不十分精确,但差距这么大(6%到95%,这也太离谱了吧?!可以说是完全颠倒了)简直让人不可思议的。
我简直要崩溃了!!!


【最后再总结一下:在p1被p3结束之后,p3会在300毫秒后马上结束p2,而p2会在距上次延时5000毫秒后才会去试图启动p1,所以往往它还来不急去启动p1,它本身也被结束了(300毫秒比5000毫秒短得多),有人问我怎么算出是6%的,这很简单:p1被结束后,p3会在300毫秒后去结束p2,而p2会在距上次延时5000毫秒后去启动p1,而它上次的延时在p1结束之前,也就是说,它会在p1结束后【0毫秒——5000毫秒】之间去启动p1,它有6%(0毫秒——300毫秒)的机会赶在被结束之前去启动p1,但更多的时候它会在300毫秒——5000毫秒的时候才会去启动p1,那时它已被终止,根本无法完成任务了。】
另外:
GetProcesses,GetProcessesByName获得的Process[]是按什么顺序排序的(肯定不是启动时间、ID号)

还有,如果在窗体的Load事件中写入代码,只有等这段代码执行完后,窗体才会被绘制出来
怎么解决这个问题呢?
也就是我启动程序后首先要绘制出窗体,然后执行一些代码(这些代码不是用户通过Click之类的事件触发的,是系统自动运行的)

--------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 这样的广告贴真让人闹心! --------------------编程问答-------------------- 我先顶再说 --------------------编程问答-------------------- 当然,可能有这样一个解释(这里p3延时为300毫秒): 
当p3结束p1时,p2据上次延时已超过4700毫秒,所以它能赶在300毫秒(到时它本身会被结束)之内启动p1 
但如果是这样,p3不能结束p1,p2的概率只有6%(300/5000)
------------------------------------------
一看就有問題,實在不知道這6%是怎么計算的.
依LZ的邏輯,如果p3是延時5000秒,p3不能结束p1,p2的概率難道就是100%(5000/5000)了??? --------------------编程问答-------------------- 你想实现守护进程
最好是实现2个进程共享某个内存来实现守护 --------------------编程问答-------------------- 何以见得为广告贴? --------------------编程问答-------------------- ? --------------------编程问答-------------------- 还有,如果在窗体的Load事件中写入代码,只有等这段代码执行完后,窗体才会被绘制出来 
怎么解决这个问题呢?
============================================================================
可以考虑用异步(新开线程)的方式来处理 --------------------编程问答-------------------- 关于进程的问题没有看得特别明白,如果进程之间要做协调,需要采用进程同步技术。
建议楼主先看一些进程同步相关的文章 --------------------编程问答-------------------- 不要用sleep();用Process.WaitForExit 试试~~~ --------------------编程问答-------------------- :)







-------------- --------------------编程问答-------------------- 回5楼:
p3如果延时过长,p2有足够的时间来启动p1,之后p2虽然会被结束,但那时p1会启动它,当然是100%不可能结束p1,p2了 --------------------编程问答-------------------- to: LZ
未必吧 --------------------编程问答-------------------- 花了一些时间,测了一下。结果如下:

首先:LZ的内部while 语句会导致CPU资源全部占用,在单个CPU的机器上会出现不确定的影响。因为,两个进程100%抢占时,结果是不可确定的。

我测试时在p1,p2内部中加了一个 1MS的小睡,其它代码相同 如下:
private   void   Form1_Load(object   sender,   EventArgs   e) 
                { 
                        while   (true) 
                        { 
                                System.Threading.Thread.Sleep(5000); 
                                while   (Process.GetProcessesByName( "p1 ").Length   >   0)   Tread.Sleep(1);                                 Process.Start( "p1 "); 
                        } 
                }

结果:
例1:近乎100%成功
KILL一个进程在我的机器上需要 15ms - 16ms 的时间
启动一个进程在我的机器上需要 31ms - 78ms 的时间

因此,在在KILL一个进程后,p3有 > 15ms的时间去KILL另一个

例2:近乎100%不成功

按照上面的例子,只要KILL的快,就可以成功,但为什么这里不成功了呢?
原因就在LZ的代码逻辑


假如启动p1 10s之后,p3的SLEEP时间设为 300
(5s后,p2被启动)

1.此时p1,p2都在判断对方是否正常,
2.KIll p1
3.1 p2不需要等待启动p1,然后进入5000的sleep
3.2 p3进入等待300
4. 300 后,kill p2
5. 5000-300后 p1启动p2

其它情况就先不分析了。

--------------------编程问答-------------------- 我觉得是系统延时的问题,当你用P3关闭P1时回产生系统延时,而线程P3的休眠时间为300太小了容易是系统不稳定,你可以尝试将线程P3的修面时间设为3000试下 --------------------编程问答-------------------- 回15楼,感谢你的亲自测试
下面是我的回复:
1.加不加小睡结果都是一样的
2.启动或结束一个进程只需数十毫秒,相对于sleep的数百数千毫秒微不足道,完全可以忽略
3.5000-300后,p1启动p2?这是不可能的,因为p1早就被kill了

另外,我通过加一些标记,发现顺序是:
p3结束p1
p2启动p1
p3结束p2
p1启动p2


这就怪了,p3只睡眠了300毫秒,p2则睡眠了0--5000毫秒(平均也有2500毫秒),它怎么能赶在自身被结束之前就去启动p1呢(要知道,发生这种情况的概率只有6%,但测试结果表明,近乎100%的情况下,它都能这样)

不可思议 --------------------编程问答-------------------- --------------------编程问答-------------------- up --------------------编程问答-------------------- 当Kill p1后,p2立马就把p1启动了。
所以,(5000-300)时间后,当p2被Kill时,p1又把p2启动。 --------------------编程问答-------------------- 学习了 --------------------编程问答-------------------- 一旦运行了就不允许关闭!看起来有点儿象流氓程序 --------------------编程问答-------------------- 如果你想实现禁止任务管理器结束进程,你可以参看下这个地址,希望对你有帮助
C#的工程原代码和具体内容可以在以下连接看到。
http://blog.csdn.net/kangkanglx/archive/2010/06/25/5692984.aspx --------------------编程问答-------------------- 持续的关注中。。。。 --------------------编程问答-------------------- 放过这陈年帖子把2007年的烂尾楼,打算盖多高,囧。 --------------------编程问答-------------------- 这层封顶了 --------------------编程问答--------------------
引用 23 楼 kangkanglx 的回复:
如果你想实现禁止任务管理器结束进程,你可以参看下这个地址,希望对你有帮助
C#的工程原代码和具体内容可以在以下连接看到。
http://blog.csdn.net/kangkanglx/archive/2010/06/25/5692984.aspx


博客写的比较好

顶起了 --------------------编程问答--------------------
引用 23 楼 kangkanglx 的回复:
如果你想实现禁止任务管理器结束进程,你可以参看下这个地址,希望对你有帮助
C#的工程原代码和具体内容可以在以下连接看到。
http://blog.csdn.net/kangkanglx/archive/2010/06/25/5692984.aspx

我觉得你的解决方案超出了LZ的需求范围,LZ应该给你100并追加 --------------------编程问答-------------------- up P --------------------编程问答-------------------- 标记下,  试验下 --------------------编程问答--------------------
引用 23 楼 kangkanglx 的回复:
如果你想实现禁止任务管理器结束进程,你可以参看下这个地址,希望对你有帮助
C#的工程原代码和具体内容可以在以下连接看到。
http://blog.csdn.net/kangkanglx/archive/2010/06/25/5692984.aspx

确实很强……
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,