2017-04-23 11 views
0

Visual Studio 2008、C#、および.NET Framework 3.5にコンソールアプリケーションがあります。キーを押すか、x分後に自動的にコンソールアプリケーションウィンドウを閉じる

アプリケーションがすべての処理を完了したら、ユーザーがキーを押すか、または数分後に自動的にウィンドウを閉じることができます。

だから、私は自分のアプリケーションの終了時:

static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); 

public static int Main(string[] args) 
{ 
    // Do some stuff 
    Console.WriteLine("Press any key to close this window."); 

    myTimer.Tick += new EventHandler(TimerEventProcessor); 
    myTimer.Interval = 5000; 
    myTimer.Start(); 

    Console.ReadKey(); 

    return 0; 
} 


private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)  
{ 
    myTimer.Stop(); 
    Environment.Exit(0); 
} 

ここでの問題は、x分が経過しており、プログラムが待っているブロックされているためにも、タイマーイベントが発生しませんされた後、そのウィンドウが近くないですキー(ReadKey)。

どのようにするのですか?

+0

あなたは、タイマーの間違った種類を使用している、あなたは、このようなコンソールアプリで 'System.Windows.Forms.Timer'を使用することはできません、あなたは「UIスレッドに依存しないタイマーを必要とします"System.Timers.Timer'のように –

答えて

1

は別のスレッドにやるべき仕事を移動しよう:

public static int Main(...) 
{ 
    new System.Threading.Thread(Work).Start(); 
} 
private void Work() 
{ 
    // work to be done here 
} 

この方法でGUIスレッドがタイマーのTickイベントを上げるための時間を持つことになります。

0

最良の場合、私は可能な解決策を見つけましたが、わからなかった。そのソリューションと

static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); 

public static int Main(string[] args) 
{ 
    // Do some stuff 
    Console.WriteLine("Press any key to close this window."); 

    myTimer.Tick += new EventHandler(TimerEventProcessor); 
    myTimer.Interval = 5000; 
    myTimer.Start(); 

    // while (!Console.KeyAvailable) 
    //{ 
    //  Application.DoEvents(); 
    //  Thread.Sleep(250); 
    //} 

    // Above code replaced with: 
    Console.ReadKey(true); 

    DisposeTmr(); 

    return 0; 
} 

private static void DisposeTmr() 
{ 
    myTimer.Stop(); 
    myTimer.Dispose(); 
} 

private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)  
{ 
    DisposeTmr(); 
    Environment.Exit(0); 
} 

問題は、タイマーのこのタイプが同期され、hereが説明したようにApplication.DoEventsを使用するために必要とされるということです。また、UIスレッドがスリープしている間、タイマはサスペンド状態のままであるため、メインUIスレッドがスリープしている間にタイマーイベントハンドラがタイマーイベントのキャプチャを続行しなくなる可能性があります。

これを避けるには、System.Timers.TimerとSystem.Threading.Timerの2つのオプションがあります。私は以下のようにSystem.Threading.Timerソリューションを実装しているし、それが完璧に動作します:

static System.Threading.Timer myTimer; 

public static int Main(string[] args) 
{ 
    // Do some stuff 
    Console.WriteLine("Press any key to close this window."); 

    myTimer = new System.Threading.Timer(TimerCallback, null, 5000, Timeout.Infinite); 

    while (!Console.KeyAvailable) 
    {   
     Thread.Sleep(250); 
    } 

    DisposeTmr(); 

    return 0; 
} 

private static void DisposeTmr() 
{ 
    if (myTimer != null) 
    { 
     myTimer.Dispose(); 
    } 
} 

private static void TimerCallback(Object myObject)  
{ 
    DisposeTmr(); 
    Environment.Exit(0); 
} 
1

あなたは持っている問題は、あなたがUIスレッド上でハングアップされたフォームのタイマーを、使用していることである - コンソールアプリの。コンソール以外の環境を終了しています。

代わりにスレッドタイマーを使用する必要があります。しかし、これはあまり変わらないはずです。

static Timer myTimer; 

    public static int Main(string[] args) 
    { 
     // Do some stuff 
     Console.WriteLine("Press any key to close this window."); 

     //Hey, I just met you and this is crazy 
     myTimer = new Timer(CallMeMaybe, null, 5000, 0); 

     //so call me maybe 
     Console.ReadKey(); 

     return 0; 
    } 

    //Instead of a tick, we have this 
    private static void CallMeMaybe(object state) 
    { 
     //But here's my number 
     Environment.Exit(0); 
    } 
関連する問題