2016-09-30 7 views
1

Ich schreibe ein Programm, das jede zweite Daten von einem seriellen Port liest und es in einer Textdatei speichert/zeige es auf der GUI. Das Lesen beginnt und endet mit einem Knopfdruck.C# timer Welchen Timer soll ich verwenden?

Ich habe versucht verschiedene Timer zu lösen, aber jeder Timer bringt einige Probleme (siehe unten).

Mein tryouts:

serialPort1.ReadTimeout = 2000;

System.Timers.Timer:

private void timer1_Tick(object sender, EventArgs e) 
    { 
     if (!serialPort1.isOpen) 
     { 
      serialPort1.Open(); 
     } 

     serialPort1.WriteLine("INFO"); //Send data command 
     string data = serialPort1.ReadLine(); 

     serialPort.Close(); 
     editData(data); //Method for GUI update and textfile log 
    } 

Kann leicht gestartet und gestoppt mit timer1.Start() und timer1.Stop(). Das Problem ist, System.Timers.Timer läuft auf GUI Threard und friert die GUI ein, während serialPort.read und serialPort.Close() aufgerufen wird.


Backgroundworker:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     while (backgroundWorker1.CancellationPending == false) 
     { 
      if (!serialPort1.isOpen) 
      { 
       serialPort1.Open(); 
      } 

      serialPort1.WriteLine("INFO"); 
      string data = serialPort1.ReadLine(); 

      serialPort.Close(); 
      Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log 
     } 
    } 

Läuft asynchronlly. Ich muss das Programm jede Sekunde ausführen.


System.Timers.Timer ruft Backgroundworker:

private void timer1_Tick(object sender, EventArgs e) 
    { 
     backgroundWorker1.RunWorkerAsync(); 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
      if (!serialPort1.isOpen) 
      { 
       serialPort1.Open(); 
      } 

      serialPort1.WriteLine("INFO"); 
      string data = serialPort1.ReadLine(); 

      serialPort.Close(); 
      Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log 
    } 

Dies funktioniert gut, bis der Datenlesevorgang länger dauert oder ein serialPort.readTimeout auftreten. Hintergrundarbeiter können nur einmal ausgeführt werden. Also ich denke, das ist keine Option.


System.Threading.Timers:

 System.Threading.Timer timer; 
     timer = new System.Threading.Timer(_ => readSerialPort(), null, 0, 950); 

     private void readSerialPort() 
     { 
      if (!serialPort1.isOpen) 
      { 
       serialPort1.Open(); 
      } 

      serialPort1.WriteLine("INFO"); 
      string data = serialPort1.ReadLine(); 

      serialPort.Close(); 
      Invoke((MethodInvoker)(() => editData(data)); //Method for GUI update and textfile log 
     } 

Dies funktioniert gut, aber das Problem ist, kann ich nicht das Lesen stoppen und neu zu starten.


Hat jemand eine Idee, welchen Timer ich in diesem Fall verwenden sollte?

+0

Nun, Sie haben Ihre Optionen umrissen und die Gründe für jede dieser hinzugefügt. Was genau erwartest du als Antwort hier? :) – Luaan

+1

System.Timers.Timer wird nicht standardmäßig auf UI-Thread ausgeführt, nur wenn Sie SynchronizingObject festlegen. – Evk

+0

@Luaan Ich bin auf der Suche nach einer Option, wo ich die Daten lesen und starten kann und die GUI sollte nicht einfrieren während serialPort.Close(),/SerialPort.ReadLine() – Snaff

Antwort

1

Über System.Threading.Timer

var timer = new System.Threading.Timer(cb, null, 1000, 1000); // init 
timer.Change(Timeout.Infinite, Timeout.Infinite); // stop 
timer.Change(0, 1000); // start 

P. S. Vergessen Sie nicht, Timer zu entsorgen

0

Sie können diese Logik mit einem Thread implementieren. Ein Metacode ist unter:

 var stopEvent = new ManualResetEvent(false); 
     var thread = new Thread(() => { 

      if (!serialPort1.isOpen) 
      { 
       serialPort1.Open(); 
      } 
      try 
      { 

       while (!stopEvent.WaitOne(0)) 
       { 
        try 
        { 
         serialPort1.WriteLine("INFO"); 
         string data = serialPort1.ReadLine(); 
         Invoke((MethodInvoker)(() => editData(data))); 

        } 
        catch (Exception) 
        { 

         // Handle exception, e.g. a reading timeout 
        } 

        stopEvent.WaitOne(1000); //Thread.Sleep(1000); 
       } 
      } finally 
      { 
       serialPort.Close(); 
      } 


     }); 
     thread.Start(); 

     //call it to stop the loop. 
     stopEvent.Set(); 
    } 

Sie können komplexere Logik implementieren, wie das Stoppen und Wiederaufnehmen von Messwerten. Benutze einfach mehr Events. Wenn Sie mit Ereignissen nicht vertraut sind, können Sie einfach boolesche Variablen verwenden, aber definieren, dass sie volatile sind.

+0

Dies ist eine gute Idee für das Arbeiten ohne Timer. Ich werde es versuchen, danke – Snaff