4 Stimmen

Führe eine Methode für eine Minute aus und stoppe sie.

timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Start();
MeineMethode();
timer1.Stop();

MeineMethode()

-hat eine Schleife für 90.000 Einträge (und einige Validierungen in dieser Schleife).

for (int i = 0; i <= 90000; i++)
{
 //Validierungen hier einfügen

}

Wenn die Zeit im timer1 abgelaufen ist, also eine Minute vergangen ist, möchte ich das Ausführen anderer Einträge in der Schleife stoppen. Wenn zum Beispiel 45.000 Einträge innerhalb einer Minute abgeschlossen sind, möchte ich die Methode stoppen, also die Methode nach einer Minute stoppen.

Allerdings führt der obige Timer-Code dazu, dass alle 90.000 Datensätze weiterhin in der Schleife durchlaufen werden, die Methode läuft jedoch irgendwie nicht für eine Minute? Kann mir jemand helfen?

3voto

Chris Punkte 26614

Zwei Dinge. Erstens ist Ihr Timercode tatsächlich nicht mit der Ausführung von MyMethodName verbunden. Ein Timer ist so konzipiert, dass Prozesse ausgeführt werden, wenn die Zeit abgelaufen ist (und möglicherweise in regelmäßigen Abständen, abhängig davon, wie er eingerichtet ist).

Zweitens und wichtiger für Ihre Frage, um eine Schleife abzubrechen, müssen Sie Code innerhalb der Schleife platzieren. Der Schlüssel wäre, eine Stoppuhr oder ähnliches vor Ihrer Schleife zu starten und dann am Anfang Ihrer Schleife zu überprüfen, wie viel Zeit vergangen ist. Wenn es eine Minute oder mehr ist, dann break;.

Das Wichtige zu beachten ist, dass Sie nicht genau nach einer Minute anhalten, sondern die Iteration der Schleife abschließen, die ausgeführt wird, wenn die Minute abläuft, und dann anhalten. Dies ist in der Regel das, was Sie wollen, da das Stoppen der Verarbeitung mitten in etwas zu unangenehmen Nebenwirkungen führen kann.

Stopuhr stopwatch = new Stopuhr();
stopuhr.Start();
for (int i =0; i<=90000; i++)
{
    if (stopuhr.Elapsed>TimeSpan.FromSeconds(5))
        break;
    Console.WriteLine(i);
    Thread.Sleep(1000);
}

Beachten Sie, dass Thread.Sleep nur dort steht, weil ich sonst alle 90000 Iterationen zu schnell durchlaufe. ;-)

2voto

Mike Perrenoud Punkte 64649

Also bräuchten Sie wahrscheinlich eine ganz andere Implementierung. Betrachten Sie dies:

public class MyForm
{
    private BackgroundWorker _worker;

    public MyForm()
    {
        _worker = new BackgroundWorker();
        _worker.DoWork += (s, args) =>
        {
            var timer = Stopwatch().StartNew();
            do
            {
                // do something
            } while (timer.ElapsedMilliseconds < 60000)
        };
    }
}

und dann wenn Sie es ausführen möchten:

_worker.RunWorkerAsync();

Sie könnten es jedoch noch robuster machen. Sie könnten die Zeit so übergeben:

_worker.RunWorkerAsync(60000);

und dann im DoWork Handler dies tun:

while (timer.ElapsedMilliseconds < (int)args.Argument)

Außerdem könnten Sie mit dem BackgroundWorker die Abbruchfunktion unterstützen. Setzen Sie einfach das WorkerSupportsCancellation Flag auf true und dann in der Bedingung folgendes:

while (timer.ElapsedMilliseconds < (int)args.Argument && !_worker.CancellationPending)

Also, wenn nötig, könnten Sie dies tun:

_worker.CancelAsync();

1voto

Machinegon Punkte 1818

Hmm, benutze stattdessen eine Stoppuhr

  Stoppuhr stoppuhr = new Stoppuhr();
    stoppuhr.Start();

for(int i= 0; i <= 90000; i++)
{
    // Die vergangene Zeit als TimeSpan-Wert abrufen.
    TimeSpan ts = stoppuhr.Elapsed;

if(ts.Seconds >= 60)
  break;

}

1voto

Reed Copsey Punkte 536986

Der obige Timer-Code führt jedoch solange aus, bis alle 90000 Datensätze innerhalb der Schleife abgearbeitet sind, irgendwie läuft die Methode jedoch nicht für eine Minute? Irgendwelche Hinweise?

Der Timer löst keine Ereignisse aus, bis Sie den UI-Thread freigeben, was erst nach Abschluss der Methode erfolgt.

Wenn Sie verhindern möchten, dass die Methode länger als eine bestimmte Zeitspanne läuft, könnten Sie dies direkt in Ihrer Methode behandeln:

MyMethodName(TimeSpan.FromMinutes(1));

Dann, in Ihrer Methode:

void MyMethodName(TimeSpan maxRuntime)
{
    DateTime expiration = DateTime.Now + maxRuntime;

    for (int i = 0; i <= 90000; i++)
    {
         //Validierungen hier durchführen

         if (i % 100 == 0) // alle 100 überprüfen?
         {
              if (DateTime.Now > expiration) 
                    break;
         }
    }
}

Dennoch wäre es besser, dies in einen Hintergrundthread zu verschieben und bei Bedarf abzubrechen.

0voto

konkked Punkte 3161

Sie können eine Flagge in Validierungen setzen, um zu sehen, ob sie durchgeführt wurde oder nicht, indem Sie einen Ereignishandler mit dem Tick-Ereignis im Timer-Objekt verknüpfen

// in einem für beide Elemente zugänglichen Bereich
object readonly _lock = new object();
bool elapsed = false;

wo Ihr ursprünglicher Code war

elapsed = false;
timer1= new System.Windows.Forms.Timer();
timer1.Interval =60000; // 1 min
timer1.Tick=((sender, everntArgs)=>
{
    lock(_lock)
        elapsed = true; 
});
timer1.Start();
MeinMethodName();
timer1.Stop();

Innerhalb von MyMethodName

// innerhalb der Schleife
for (int i = 0; i <= 90000; i++)
{
    // Validierungen hier einfügen
    lock(_lock)
        if(elapsed)
            break;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X