2011-11-17 8 views
1

타이머를 중지 한 후에도 내 이벤트 핸들러가 전화를 끊지 않는 이유는 무엇입니까? 내 코드에 문제가 있습니까? 도와주세요!C# 타이머 종료 후 이벤트 처리기 중지

나는 너희들이 나에게 도움이 할 수 있다면 결코 기록되지 타이머를 발사로이 세 가지 방법 (방지 도착하기 때문에,

private void Form1_Load(object sender, EventArgs e) 
    { 
     //Start system 
     axInRFIDCtrl1.SelectReaderFeig(); 
     axInRFIDCtrl1.FEInit(); 
     short sResult = axInRFIDCtrl1.FEOpen(); 
     //MessageBox.Show(sResult.ToString()); 

     //Start timer1 
     System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer(); 
     timer1.Interval = 1000; 
     timer1.Tick += new EventHandler(timer1_Tick); 
     timer1.Enabled = true; 
     timer1.Start(); 

     Console.ReadLine(); 
    } 

    public void timer1_Tick(object sender, EventArgs e) 
    { 
     //Get ID 
     string strTagIds = string.Empty; 
     int iState = 0; 

     axInRFIDCtrl1.FESelect(ref strTagIds, ref iState); 

     string[] strTagID = strTagIds.Split(new char[] { '|' }); 
     string strTag = strTagID[0]; 
     textBox1.Text = strTag; 

     //Connection to datebase 
     string c1 = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Project.mdb"; 
     OleDbConnection con = new OleDbConnection(c1); 

     //Bind button 
     string txt = textBox1.Text; 

     string strOleDbConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Project.mdb"; 
     string strSqlStatement = string.Empty; 
     strSqlStatement = "SELECT * FROM jiahe WHERE [Tag ID] = '" + txt + "'"; 
     OleDbConnection objConnection = new OleDbConnection(strOleDbConnectionString); 
     OleDbDataAdapter objAdapter = new OleDbDataAdapter(strSqlStatement, objConnection); 
     DataSet ds = new DataSet(); 
     objAdapter.Fill(ds); 

     DataTable dt = ds.Tables[0]; 
     dataGridView1.DataSource = dt.DefaultView; 

     if (dt.Rows.Count == 1) 
     { 
      string strLine = string.Empty; 
      string strUser = string.Empty; 

      foreach (DataRow dr in dt.Rows) 
      { 
       string strTags = dr["Tag ID"].ToString(); 
       strUser = dr["User"].ToString(); 
       string strAge = dr["Age"].ToString(); 
       string strPhoneNumber = dr["Phone Number"].ToString(); 

       // prepare command string 
       string selectString = @"SELECT Status FROM jiahe where [Tag ID] = '" + textBox1.Text + "'"; 

       // 1. Instantiate a new command with command text only 
       OleDbCommand cmd = new OleDbCommand(selectString, objConnection); 

       // 2. Set the Connection property 
       cmd.Connection.Open(); 

       // 3. Call ExecuteScalar to send command 
       string str = cmd.ExecuteScalar().ToString(); 

       cmd.Connection.Close(); 

       foreach (DataRow datarow in dt.Rows) 
       { 
        //string strName = string.Empty; 
        strName = datarow["User"].ToString(); 

        if (str.Length == 2 || str.Length == 0) 
        { 
         // prepare command string 
         string updateString = @"update jiahe set Status = 'OUT' where [Tag ID] = '" + textBox1.Text + "'"; 

         // 1. Instantiate a new command with command text only 
         OleDbCommand cmd1 = new OleDbCommand(updateString, objConnection); 

         // 2. Set the Connection property 
         cmd1.Connection.Open(); 

         // 3. Call ExecuteNonQuery to send command 
         str = cmd1.ExecuteNonQuery().ToString(); 
         cmd1.Connection.Close(); 

         //write text file to outgoing spool 
         //TextWriter tw = new StreamWriter(@"C:\cygwin\var\spool\sms\outgoing\sms.txt"); 

         TextWriter tw = new StreamWriter(@"C:\\Test.txt"); 
         { 
          tw.WriteLine("To: 6592786618\n"); 
          tw.WriteLine("\n"); 
          tw.WriteLine("\n" + strName + @" has just left at " + DateTime.Now); 
          tw.Close(); 
         } 

         MessageBox.Show(strName + " has left the house."); 

         //Start timer2 
         System.Windows.Forms.Timer timer2 = new System.Windows.Forms.Timer(); 
         timer2.Interval = 1000 * 60 * 30; //30 mins interval 
         timer2.Tick += new EventHandler(timer2_Tick); 
         timer2.Enabled = true; 
         timer2.Start(); 

         //Log to listbox 
         // Set the selection mode to multiple and extended. 
         listBox1.SelectionMode = SelectionMode.MultiExtended; 
         listBox1.BeginUpdate(); 
         listBox1.Items.Add(DateTime.Now + " - " + strName + " > OUT"); 
         listBox1.EndUpdate(); 

         //Log event to log file 
         string cs = "Minder+Finder Event Log"; 
         EventLog elog = new EventLog(); 

         if (!EventLog.SourceExists(cs)) 
         { 
          EventLog.CreateEventSource(cs, cs); 
         } 

         elog.Source = cs; 
         elog.EnableRaisingEvents = true; 
         elog.WriteEntry(DateTime.Now + " - " + strName + " > OUT"); 
        } 
        else 
        { 
         // prepare command string 
         string updateString = @"update jiahe set Status = 'IN' where [Tag ID] = '" + textBox1.Text + "'"; 

         // 1. Instantiate a new command with command text only 
         OleDbCommand cmd1 = new OleDbCommand(updateString, objConnection); 

         // 2. Set the Connection property 
         cmd1.Connection.Open(); 

         // 3. Call ExecuteNonQuery to send command 
         str = cmd1.ExecuteNonQuery().ToString(); 
         cmd1.Connection.Close(); 

         //write text to outgoing spool 
         TextWriter tw = new StreamWriter(@"C:\\Test.txt"); 
         //using (TextWriter tw = File.CreateText("C:\cygwin\var\spool\sms\outgoing\Test.txt")); 
         { 
          tw.WriteLine("To: 6592786618\n"); 
          tw.WriteLine("\n"); 
          tw.WriteLine("\n" + strName + @" has just returned home at " + DateTime.Now); 
          tw.Close(); 
         } 
         MessageBox.Show(strName + " has returned home."); 

         //Stop timer2 
         timer2.Tick -= timer2_Tick; 
         timer2.Enabled = false; 
         timer2.Stop(); 

         //Log to listbox 
         // Set the selection mode to multiple and extended. 
         listBox1.SelectionMode = SelectionMode.MultiExtended; 
         listBox1.BeginUpdate(); 
         listBox1.Items.Add(DateTime.Now + " - " + strName + " > IN"); 
         listBox1.EndUpdate(); 

         //Log event to log file 
         string cs = "Minder+Finder Event Log"; 
         EventLog elog = new EventLog(); 

         if (!EventLog.SourceExists(cs)) 
         { 
          EventLog.CreateEventSource(cs, cs); 
         } 

         elog.Source = cs; 
         elog.EnableRaisingEvents = true; 
         elog.WriteEntry(DateTime.Now + " - " + strName + " > IN"); 

        } 
       } 
      } 
     } 
     else 
     { 
      timer1.Enabled = false; 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     Form2 form2 = new Form2(); 
     form2.ShowDialog(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     Form3 form3 = new Form3(); 
     form3.ShowDialog(); 
    } 

    public void timer2_Tick(object sender, EventArgs e) 
    { 
     MessageBox.Show(strName + " has left"); 

     //write text file to outgoing spool 
     //TextWriter tw = new StreamWriter(@"C:\cygwin\var\spool\sms\outgoing\sms.txt"); 
     TextWriter tw = new StreamWriter(@"C:\\Test1.txt"); 
     { 
      tw.WriteLine("To: 6592786618\n"); 
      tw.WriteLine("\n"); 
      tw.WriteLine("\n" + strName + @" has just left at " + DateTime.Now); 
      tw.Close(); 
     } 
    } 
+0

다른 이름이 뭔가요? –

+3

"timer2.Interval = 2000; // 30 분 간격"-별로 아닙니다. 2 초입니다. – Joe

+0

그 사이에 어떤 일이 발생합니까? 동일한 타이머 인스턴스에서 탈퇴 하시겠습니까? –

답변

2

timer2가 인스턴스 변수 인 경우 문제는 timer2라고도하는 로컬 변수를 만들고 시작하는 것입니다. 그런 다음 로컬 변수 timer2가 아닌 timer2 변수를 중지합니다. 로컬 범위 timer2는 가비지 컬렉터가 처분 할 때까지 계속 실행됩니다.

저는 timer2가 인스턴스 변수라고 확신합니다. 그렇지 않으면 다른 참조가 컴파일되지 않습니다. 또한 루프 내부에 timer2를 생성하기 때문에 아마도 보트로드가 생성 될 것이며 가비지 수집기가 불행에서 벗어날 때까지 모두 행복하게 사라집니다.

편집 : 여기에 양식 내에서 사용하는 간단한 예제가 있습니다.

http://www.java2s.com/Code/CSharp/GUI-Windows-Form/GUIandtimer.htm

당신은 단순히 양식 디자인에 타이머 구성 요소를 삭제하는 경우는, 다음 초기화는 다음 예제와 같이 InitializeComponents 방법에 당신을 위해 작성되었습니다. 이것 이외에, 나는 훨씬 더 많은 것을 도울 수 없다. 타이머를 사용하는 방식에 구조적인 문제가 있다고 생각합니다. 시작과 중지, 특히 for 루프의 timer2가 많은 어려움과 두통을 유발하는 것처럼 보입니다.

+0

좀 좀 먹어. 변수를 어떻게 작성해야합니까? –

+0

생성자에서 timer2를 한 번 생성하거나 객체 인스턴스를 초기화합니다. 그런 다음 모든 것이 그 단일 인스턴스를 참조합니다. 양식 배관은 양식 클래스에 포함 된 방법에 따라 양식을 작성할 수 있습니다. – hatchet

+0

내 타이머 1을 볼 수 있습니까? Timer1_Tick 이벤트 핸들러를 timer1이 호출 할 때 호출하는 방법을 이상하게 생각한 다음 timer1을 주석 처리하더라도 Timer1_Tick이 여전히 "놀랍게도"호출됩니다. 왜? –

-1

이 코드를 :) 제발, 안에 내 전체 코드를 포함 시켰습니다) 시간이 경과하기 전에. 당신의 진짜 문제에 관해서는

//Stop timer2 
timer2.Stop(); 
timer2.Tick -= timer2_Tick; 

... 우리는 코드의 나머지는 당신을 도울 볼 필요가 :

+0

... 코멘트 여야합니다. –

1

귀하의 중지 코드는 다음과 같이 더 좋을 것이다.

+0

나머지 코드를 포함 시켰습니다. 한번보십시오. –

+0

RFID가 없으면 아무것도 테스트 할 수 없습니다. 또한 해결책이 아니라면 답을 해결책으로 받아들이는 것이 좋지 않습니다. 그 말로는, 당신의 코드에서 문제가 될지도 모르는 것들이 있습니다 : 1) timer1의 tick에서 timer2를 활성화하고 있습니다. 이것은 따르거나 유지하기가 쉽지 않습니다. 2.) else 블록에서 타이머 2를 멈추고 있지만 다른 db2에서 멈추는 것을 안다면 블록 시작 부분에서 그것을 수행하십시오. 3.) 몇 가지 중단 점을 설정하고 따라하십시오. 여기에 대답이 있습니다. 마법이 아닙니다. – rfmodulator

2

Stop() 또는 Enabled = false을 호출하여 타이머를 중지하면 다시 시작되지 않습니다. 내가 결코 중단 타이머가 이벤트 처리기를 호출하는 경우를 보았다. 타이머를 사용하지 않도록 설정 한 후에도 이벤트 핸들러가 여전히 호출 중이면 다른 코드가 타이머를 호출하거나 뭔가 타이머를 다시 활성화합니다.

이벤트 처리기가 현재 실행중인 경우 타이머를 중지해도 이벤트가 중단되지 않습니다. 또한 보류중인 이벤트를 막지 않습니다. 그 이벤트 핸들러는 항상 GUI 스레드에서 실행되기 때문에 그걸 System.Windows.Forms.Timer과 관련해서는 안됩니다.

나는 코드를 매우 조심스럽게 검사하고 타이머가 활성화되거나 비활성화 된 모든 장소를 보았습니다. 타이머에 다시 활성화되는 코드가 있음을 알게 될 것입니다.

편집하여 게시 된 코드 본 후 :

을 가능성이 문제는 타이머 이벤트 처리기에서 다음 가지고있다 : 다른 것 로컬 timer2 변수를 생성

System.Windows.Forms.Timer timer2 = new System.Windows.Forms.Timer(); 
// code that initializes and enables timer 

당신의 timer2은 양식 범위에 있습니다 (코드 컴파일을 암시하고 별도의 범위에서 timer2을 참조 함). 새 타이머가 생성되지만 타이머를 비활성화하는 코드는 폼 범위 timer2을 참조합니다. 그래서 일어나고있는 일은 당신이 많은 다른 타이머를 만들고 있고, 그것들 모두가 같은 이벤트 핸들러를 호출하는 것입니다.

이벤트 핸들러에서 MessageBox.Show으로 전화하는 것이 디버깅 용도로 사용되기를 바랍니다. UI 스레드를 차단하고 해지 될 때까지 추가 타이머 틱을 방지하므로 사용자는 거기에 남기고 싶지 않습니다.

+0

정말 분명합니다. 나는 코드를 무수히 확인했지만 여전히 문제를 찾을 수없는 것 같습니다. –

+0

나는 그것을 지금 얻었다. 그러나, 같은 일이 내가 실제로 Form_Load에서 timer1을 주석으로 timer1_Tick eventhandler 여전히 호출됩니다 timer1에 대해 발생합니다. 이게 왜 그렇게? –

+0

System.Windows.Forms.Timer를 제거하면됩니다. timer2 = new System.Windows.Forms.Timer(); 정말 고마워요! –