除了使用while之外,还有更好的方法可以让控制台应用程序无法返回吗?

时间:2014-09-18 12:29:59

标签: c# .net timer console-application

我有一个小型C#控制台应用程序,它运行一些代码,然后检查要完成的特定可执行文件。

我遇到的问题(我通常不会编写控制台应用程序)就是当我找到检查可执行文件终止的代码时,我的Main()返回并且控制台应用程序关闭。检查可执行文件的代码是通过Timer()运行的。目前我通过添加while(true){}保持Main活着,这似乎正在起作用,除了它(显然)占用了大量的CPU时间。

是否有更好的方法可以阻止Main()函数返回?

    static Timer tmrCheck = new Timer();
    static void Main(string[] args)
    {
        Initialize();
        while (true) ; // If this line is removed, the application will close after
                       // the last line of Initialize() is run.
    }

    static void Initialize()
    {
        tmrCheck.Elapsed += tmrCheck_Elapsed;
        tmrCheck.Interval = 10000;
        tmrCheck.Enabled = true; // After this line, Initialize returns to Main()
    }

    static void tmrCheck_Elapsed(object sender, ElapsedEventArgs e)
    {
        // Get a list of processes
        // Check to see if process has exited
        // If so, run *this* code then exit console application.
        // If not, keep timer running.
    }

5 个答案:

答案 0 :(得分:1)

如果您只需要等到已启动的流程退出 这可以写在Timer.Elapsed事件

Process[] p = Process.GetProcessesByName("yourprocessname");
if(p.Length > 0) 
{
    p[0].WaitForExit();
    Console.WriteLine("Finish");    
}
else
{ 
    // Do other things
}

修改
看起来这可以尝试。我不确定这里的线程问题,所以等待更多的专家指出这种方法的弱点

static Timer tmrCheck = new Timer();
static bool waiting = false;
static void Main(string[] args)
{
    Initialize();
    Console.WriteLine("Press enter to stop the processing....");
    Console.ReadLine();
    tmrCheck.Stop();
}

static void Initialize()
{
    tmrCheck.Elapsed += (s, e) =>
    {
        Console.WriteLine("Timer event");
        if(!waiting)
        {
            Process[] p = Process.GetProcessesByName("yourprocessname");
            if(p.Length > 0)
            {
                waiting = true;
                Console.WriteLine("Waiting for exit");
                p[0].WaitForExit();
                Timer t = s as Timer;
                t.Stop();
                Console.WriteLine("Press enter to end application");

            }
        }
        else
        {
            // other processing activities
        }
    };
    tmrCheck.Interval = 10000;
    tmrCheck.Enabled = true; 
}

答案 1 :(得分:0)

尝试:Thread.Sleep(1);在你的while循环中。即使睡眠一毫秒也可以节省大量的CPU周期。

希望有所帮助

答案 2 :(得分:0)

你可以像其他人一样使用Thread.Sleep并像这样重写你的代码:

static void Main(string[] args)
{
   while (true) 
   {
        // Get a list of processes
        // Check to see if process has exited
        // If so, run *this* code then exit console application.
        // If not, keep timer running.
       Thread.Sleep(10000); // Wait 10s and retry your previous actions
   }
}

另一个建议(我有时使用线程取消选项)

static void Main(string[] args)
{
   int timeout = 10;
   int timeoutCount = 10;
   while (true) 
   {
      //Here you can check cancellation flag

      if(timeout == timeoutCount)
      {
        timeoutCount = 0;
        // Get a list of processes
        // Check to see if process has exited
        // If so, run *this* code then exit console application.
        // If not, keep timer running.
      }
      Thread.Sleep(1000); // Wait 1s and retry your previous actions
      timeoutCount++;
   }
}

答案 3 :(得分:0)

您可以尝试这样的事情:

static void Main(string[] args)
{
    var procs = Process.GetProcessesByName("LINQPad").ToList();

    if (procs.Any())
    {
        procs.ForEach(p => p.EnableRaisingEvents = true);
        procs.ForEach(p => p.Exited += OnExited);
        procs.ForEach(p => p.WaitForExit());
    }

    Console.WriteLine("All processes exited...");
    Console.ReadKey();
}

private static void OnExited(object sender, EventArgs eventArgs)
{
    Console.WriteLine("Process Has Exited");
}

您没有提及是否正在监控多个进程,但是您可以删除.ForEach语句并为单个进程执行相同的逻辑,如果没有。此外,我不确定Console.ReadKey()是否是您为防止进程退出而想到的...或者您是否只需要让它不会退出直到进程关闭。< / p>

答案 4 :(得分:0)

您没有说明您正在使用的.Net框架的版本,或者应用程序是否启动了该流程,但是......如果您使用的是4.0或更高版本并且该应用确实启动了该流程,那么您可以使用任务(System.Threading.Tasks)启动进程和Task.Wait。

using System.Threading.Tasks;
static Timer tmrCheck = new Timer();
Task doWork;
static void Main(string[] args)
{
    Initialize();
     /// do more work if required
    doWork.Wait();

}

static void Initialize()
{
    tmrCheck.Elapsed += tmrCheck_Elapsed;
    tmrCheck.Interval = 10000;
    tmrCheck.Enabled = true; // After this line, Initialize returns to Main()
   // Initialize() seems the place to do start up, but this code could move to where ever the proocess is started.
    doWork = Task.Factory.StartNew(() =>
            {
                startTheProcessHere();
            }
        );
}

Pluralsight有一个很好的课程:Introduction to Async and Parallel Programming in .NET 4