2013-05-03 34 views
0

當我用F10按鈕逐步調試這個小程序時,程序是合理的,直到達到timer.Elapsed +=的水平。在此之後,它應該去打電話給我的方法Check(MyConn),但它不!它回到MyConn.Close();,它在這兩者之間反彈,然後突然關閉程序!C中的方法和計時器#

我想知道問題來自哪裏......可能是從這一行開始的:timer.Elapsed += (timerSender, timerEvent) => timer_Elapsed(timerSender, timerEvent, MyConn);?這是一個解決方案張貼在這個論壇上,如果我想在參數MyConntimer_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" 
} 
+1

幾件事 - 什麼是例外? 'Check'用'MyConn'對象做什麼?因爲您在*之前立即關閉連接*計時器有機會使用它。 – James 2013-05-03 11:10:23

回答

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); 
    } 
} 
+0

我不知道事件是在另一個線程上,現在它是有道理的,因爲它們在同一時間運行。我想要的是每一圈時間(在我的例子中2秒),執行我的方法「檢查(MyConn)」。隨着你寫它的方式,你把「Thread.Sleep(3000)」是否意味着你讓主線睡眠3秒?如果是這樣,我看不到如何運行「檢查(MyConn)」方法,因爲您之前關閉了連接,不是? – Mike 2013-05-03 11:25:23

+0

是的。 'Thread.Sleep(3000)'表示等待3秒鐘。我不知道你的'Check'正在檢查什麼。它是否檢查打開或關閉的連接?或者嘗試別的東西?當然,您可以在關閉連接的代碼之前移動我的延遲代碼。 – 2013-05-03 11:30:32

+0

我根據您的要求更新了我的答案。 – 2013-05-03 11:31:15

3

這是完全正常的行爲。

timer.Elapsed +=代碼只註冊一個事件。 2秒後,事件將被觸發,但主線程將繼續正常並返回到Main()函數。然後它會呼叫MyConn.Close(),然後結束Main()功能。

如果這是一個控制檯應用程序,那麼它將是程序的結束,這意味着沒有時間運行timer_Elapsed事件。

如果它是一個「活着」的應用程序,就像服務或表單應用程序一樣,那麼在timer_Elapsed事件觸發時,連接將已經關閉。


,如果你有一個「活着」的應用程序,我建議,那麼你應該打開/關閉連接代碼移動到實際利用它們的功能。在這種情況下,將在timer_Elapsed事件中。

如果你沒有「活着」應用程序,那麼你可能應該完全避免定時器(以及任何帶有單獨線程的東西)。順便說一下,我一直說「保持活力」,希望你明白我的意思。我不知道用更專業的術語來形容它。

+0

其實我有一個控制檯應用程序。謝謝,現在我明白了線程的行爲。但我怎麼能解決,如果我想我的方法「檢查(MyConn);」運行每一圈時間(在我的例子中2秒),同時擱置主要的線程?? – Mike 2013-05-03 11:30:10

+0

@Mike:你可以在你的'Main'函數中使用一個while循環,每個循環睡一秒鐘。爲了避免它是無限的,你需要檢查每個循環,看它是否應該退出。你如何設置這個標誌取決於你在做什麼 – musefan 2013-05-03 11:57:20

+0

我想做一種自動檢查,我想我的方法檢查每2秒無限次地運行......我假設這意味着主要不能關閉,不是嗎?我希望主線程不要關閉連接,只要定時器事件觸發方法檢查...這是我正在嘗試做的! – Mike 2013-05-03 12:14:55