Frage

Ich habe einen Timer, der nicht benötigt, um seine verstrichene Ereignishandler zur gleichen Zeit zu verarbeiten. Aber Verarbeitung eines Abgelaufene Ereignis können mit anderen stören. Ich implementierte die Lösung unten, aber etwas fühlt sich falsch; es scheint, als ob entweder ich sollte den Timer anders oder unter Verwendung eines anderen Objekts innerhalb des Threading Raum werden. Der Timer schien am besten zu passen, weil ich regelmäßig für einen Status tun müssen, um zu überprüfen, aber manchmal dauert die Überprüfung länger als mein Intervall. Ist dies der beste Weg, um diesen Ansatz?

// member variable
private static readonly object timerLock = new object();
private bool found = false;


// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
  lock(timerLock)
  {
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
  }
}
War es hilfreich?

Lösung

Sie könnten Autoreset auf false gesetzt, dann explizit den Timer zurückgesetzt, nachdem Sie es getan umgehen. Natürlich, wie Sie es wirklich Griff hängt davon ab, wie Sie den Timer für den Betrieb erwarten. würde es auf diese Weise tun, lassen Sie Ihrem Timer von dem tatsächlichen angegebenen Intervall abdriften (wie es zu stoppen und neu zu starten). Ihr Mechanismus erlauben würde, jedes Intervall Feuer und behandelt werden, aber es kann in einem Rückstand von nicht behandeln Ereignisse führen, die jetzt, wo in der Nähe des Ablaufs des Timers gehandhabt werden, dass die Handler verursachen aufgerufen werden.

timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed += Timer_OnElapsed;
timer.AutoReset = false;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
    timer.Start();
}

Andere Tipps

Ich halte in der Regel den Timer während der Verarbeitung es, geben Sie einen try / finally-Block, und wieder den Timer, wenn Sie fertig.

Wenn LookForItWhichMightTakeALongTime() eine lange Zeit in Anspruch nehmen wird, würde ich vorschlagen, keine System.Windows.Forms.Timer verwenden, weil damit Ihren UI-Thread wird perren und der Benutzer kann die Anwendung töten denkt, dass es gefroren ist.

Was könnten Sie verwenden ein BackgroundWorker (zusammen mit einem Timer wenn dies gewünscht wird).

public class MyForm : Form
{
  private BackgroundWorker backgroundWorker = new BackgroundWorker();

  public MyForm()
  {
    InitializeComponents();
    backgroundWorker.DoWork += backgroundWorker_DoWork;
    backgroundWorker.RunWorkerCompleted +=
                                backgroundWorker_RunWorkerCompleted;
    backgroundWorker.RunWorkerAsync();
  }

  private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
  {
    e.Result = LookForItWhichMightTakeALongTime();
  }

  private void backgroundWorker_RunWorkerCompleted(object sender,
                                             RunWorkerCompletedEventArgs e)
  {
    found = e.Result as MyClass;
  }
}

Und Sie können RunWorkerAsync() rufen von überall Sie wollen, sogar von einem Timer wenn Sie möchten. Und stellen Sie sicher, zu überprüfen, ob die BackgroundWorker bereits läuft seit RunWorkerAsync() anruft, wenn es läuft eine Exception aus.

private void timer_Tick(object sender, EventArgs e)
{
  if (!backgroundWorker.IsBusy)
    backgroundWorker.RunWorkerAsync();
}
timer.enabled = false

oder

timer.stop();

und

timer.enabled = true

oder

timer.start();

Ich verwende die System.Threading.Timer wie so

 class Class1
    {
        static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));

        private static void DoSomething(object state)
        {
            timer = null; // stop timer

            // do some long stuff here

            timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }



    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top