0

この小さなプログラムを F10 キーで段階的にデバッグすると、プログラムはレベル に達するまで合理的ですtimer.Elapsed +=。この後、私のメソッドを呼び出すことになってCheck(MyConn)いますが、そうではありません! に戻りMyConn.Close();、これら 2 つの間を行き来し、突然プログラムを閉じます。

私は問題がどこから来たのか疑問に思っていました...それはこの行から来るのでしょうか: timer.Elapsed += (timerSender, timerEvent) => timer_Elapsed(timerSender, timerEvent, MyConn);? MyConnこれは、私が議論したい場合に備えて、このフォーラムに投稿された解決策でしたtimer_Elapsed...

よろしくお願いします。

static void Main(string[] args)
{
    // create connection
    string ConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\mike\\Documents\\Database1.mdb;";

    OleDbConnection MyConn = new OleDbConnection(ConnStr);
    MyConn.Open();

    initTimer(MyConn);

    MyConn.Close();
}

static void initTimer(OleDbConnection MyConn)
{
    //set up a timer
    Timer timer = new Timer();
    timer.Interval = 2000; // check every 2s (2000ms) if the values in the database changed
    timer.Enabled = true; //enable the timer, so when the timer elapses after 2s, it performs some calculations

    timer.Elapsed += (timerSender, timerEvent) => timer_Elapsed(timerSender, timerEvent, MyConn);
}

static void timer_Elapsed(object sender, ElapsedEventArgs e, OleDbConnection MyConn)
{
    Check(MyConn); // Check is a method I have in my program which takes as argument "MyConn"
}
4

2 に答える 2

3

これは完全に正常な動作です。

timer.Elapsed +=コードはイベントを登録するだけです。2 秒後にイベントが発生しますが、メイン スレッドは通常どおり続行され、関数に戻りMain()ます。次に、関数を呼び出しMyConn.Close()て終了しMain()ます。

これがコンソール アプリケーションの場合、プログラムは終了します。つまり、timer_Elapsedイベントを実行する時間がありません。

サービスやフォーム アプリケーションのように「存続する」アプリケーションの場合は、timer_Elapsedイベントが発生するまでに、いずれにせよ接続は既に閉じられています。


「生き続ける」アプリをお持ちの場合は、Open/Close 接続コードを、実際にそれらを使用する関数に移動することをお勧めします。この場合、どちらがtimer_Elapsedイベント内になります。

「生き続ける」アプリがない場合は、おそらくタイマー (および別のスレッドを持つもの) を完全に避ける必要があります。

ところで、私は「生きていなさい」と言い続けています。それを説明するためのより専門的な用語を知りません。

于 2013-05-03T11:12:09.180 に答える
2

タイマーを設定すると、コードはそのまま実行され続けます。メソッドを離れてinitTimerから、接続を閉じます。その後、Main関数が終了し、アプリケーションが閉じます。また、タイマーは終了します。

プログラムが終了していない場合、タイマーは 2000 からカウントダウンします。タイマーがゼロになると、イベントが発生します。これは別のスレッドで発生し、メインシアターと並行して発生します。あなたも接続をチェックしますが、明らかに閉じられます。

イベントが発生するまで主な脅威を待機させたい場合、タイマーを使用する必要はありません。なぜこれをしないのですか?

static void Main(string[] args)
{
    // create connection
    string ConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\mike\\Documents\\Database1.mdb;";

    using(OleDbConnection MyConn = new OleDbConnection(ConnStr))
    {
        MyConn.Open();
        do
        {
            Thread.Sleep(2000); 
            Check(MyConn);  
        }
        while(someValueToIndicateTheApplicationCanTerminate);
    }
}
于 2013-05-03T11:12:17.370 に答える