Frage

wie ein Timeout für eine beschäftigte Methode + C # gesetzt hat.

War es hilfreich?

Lösung

Ok, hier ist die wirkliche Antwort.

...

void LongRunningMethod(object monitorSync)
{
   //do stuff    
   lock (monitorSync) {
     Monitor.Pulse(monitorSync);
   }
}

void ImpatientMethod() {
  Action<object> longMethod = LongRunningMethod;
  object monitorSync = new object();
  bool timedOut;
  lock (monitorSync) {
    longMethod.BeginInvoke(monitorSync, null, null);
    timedOut = !Monitor.Wait(monitorSync, TimeSpan.FromSeconds(30)); // waiting 30 secs
  }
  if (timedOut) {
    // it timed out.
  }
}

   ...

Das vereint zwei der am meisten Spaß Teile von C #. Zunächst einmal, die Methode asynchron aufrufen, verwenden Sie einen Delegierten, die die Phantasie-Hosen BeginInvoke Magie hat.

Verwenden Sie dann einen Monitor eine Nachricht aus dem LongRunningMethod zurück zu senden an die ImpatientMethod es wissen zu lassen, wenn es fertig ist, oder wenn es von ihm in einer gewissen Zeit nicht gehört hat, nur auf sie verzichten.

(p.s.- Scherz darüber die wirkliche Antwort zu sein. Ich weiß, es gibt 2 ^ 9303 Möglichkeiten, die Haut eine Katze. Vor allem in .Net)

Andere Tipps

Sie können nicht tun, wenn Sie die Methode ändern.

Es gibt zwei Möglichkeiten:

  1. Das Verfahren ist so gebaut, dass sie sich misst, wie lange es in Betrieb war, und kehrt dann vorzeitig, wenn es eine gewisse Schwelle überschreitet.
  2. Das Verfahren so aufgebaut ist, dass es eine Variable / Ereignis überwacht, die sagen „wenn diese Variable gesetzt ist, bitte verlassen“, und dann haben Sie einen anderen Thread in dem ersten Verfahren verbrachte die Zeit messen, und dann festgelegt, dass Variable, wenn die Zeit abgelaufen bestimmte Schwelle überschritten hat.

Die naheliegendste, aber leider falsch, beantworten Sie hier erhalten können, ist „einfach das Verfahren in einem Thread ausgeführt und Thread.Abort verwenden, wenn es zu lange lief hat“.

Der einzig richtige Weg ist für das Verfahren in einer solchen Art und Weise zusammenarbeiten, dass es eine saubere Ausfahrt tun, wenn es zu lange gelaufen ist.

Es gibt auch einen dritten Weg, in dem Sie das Verfahren auf einem separaten Thread ausführen, aber nach dem Warten, bis es beendet, und es dauert zu lange, das zu tun, man einfach sagen: „Ich werde nicht warten, bis es beendet , sondern entsorgen sie sie einfach“. In diesem Fall wird immer noch die Methode ausführen und beendet schließlich, aber der andere Thread, den es wartet einfach aufgeben.

Denken Sie an der dritten Möglichkeit, wie jemand anruft und bittet sie, ihr Haus für dieses Buch zu suchen, die Sie sie geliehen, und nach 5 Minuten auf dem Ende des Telefons warten sagen Sie einfach „aw, klemmt es“, und hängen Nach oben. Schließlich, dass eine andere Person das Buch finden und zurück zu dem Telefon bekommen, nur um bemerken, dass Sie nicht mehr für das Ergebnis sorgen.

Während MojoFilter Antwort ist schön es kann zu Undichtigkeiten führen, wenn die „LongMethod“ friert. Sie sollten den Vorgang abbrechen, wenn Sie mehr im Ergebnis nicht interessiert sind.

public void LongMethod()
{
    //do stuff
}

public void ImpatientMethod()
{
    Action longMethod = LongMethod; //use Func if you need a return value

    ManualResetEvent mre = new ManualResetEvent(false);

    Thread actionThread = new Thread(new ThreadStart(() =>
    {
        var iar = longMethod.BeginInvoke(null, null);
        longMethod.EndInvoke(iar); //always call endinvoke
        mre.Set();
    }));

    actionThread.Start();
    mre.WaitOne(30000); // waiting 30 secs (or less)
    if (actionThread.IsAlive) actionThread.Abort();
}

Dies ist eine alte Frage, aber es hat eine einfachere Lösung jetzt, nicht zur Verfügung stand dann: Aufgaben

!

Hier ist ein Beispielcode:

var task = Task.Run(() => LongRunningMethod());//you can pass parameters to the method as well
if (task.Wait(TimeSpan.FromSeconds(30)))
    return task.Result; //the method returns elegantly
else
    throw new TimeoutException();//the method timed-out

Sie können die Methode in einem separaten Thread ausführen und überwachen, und es zwingen, zu beenden, wenn es zu lange arbeitet. Ein guter Weg, wenn man sich als solche bezeichnen kann, wäre ein Attribut für das Verfahren in Beitrag Sharp so wird die Beobachtung Code Ihrer Anwendung nicht verunreinigen.

Ich habe folgendes als Beispielcode (beachten Sie den Beispielcode Teil, es funktioniert, könnte aber Probleme von Multithreading leiden, oder wenn das betreffende Verfahren die Threadabort erfasst würde es brechen) geschrieben:

static void ActualMethodWrapper(Action method, Action callBackMethod)
{
    try
    {
        method.Invoke();
    } catch (ThreadAbortException)
    {
        Console.WriteLine("Method aborted early");
    } finally
    {
        callBackMethod.Invoke();
    }
}

static void CallTimedOutMethod(Action method, Action callBackMethod, int milliseconds)
{
    new Thread(new ThreadStart(() =>
    {
        Thread actionThread = new Thread(new ThreadStart(() =>
        {
            ActualMethodWrapper(method, callBackMethod);
        }));

        actionThread.Start();
        Thread.Sleep(milliseconds);
        if (actionThread.IsAlive) actionThread.Abort();
    })).Start();
}

Mit dem folgenden Aufruf:

CallTimedOutMethod(() =>
{
    Console.WriteLine("In method");
    Thread.Sleep(2000);
    Console.WriteLine("Method done");
}, () =>
{
    Console.WriteLine("In CallBackMethod");
}, 1000);

Ich muss auf meine Lesbarkeit des Codes arbeiten.

Methoden haben keine Timeouts in C #, es sei denn, Ihr im Debugger oder das Betriebssystem glaubt, Ihre App ‚gehangen‘. Selbst dann setzt sich die Verarbeitung noch und solange man nicht die Anwendung töten eine Antwort zurückgegeben wird und die App weiter arbeiten.

Anrufe auf Datenbanken können Timeouts haben.

Können Sie eine Asynchronous Methode erstellen, so dass Sie auch weiterhin tun andere Sachen, während die „busy“ Methode abgeschlossen ist?

ich apps regelmäßig schreiben, wo ich zeitkritische Aufgaben über Plattformen hinweg synchronisieren müssen. Wenn Sie vermeiden können, Thread.Abort Sie sollten. Siehe http: // blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx und http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation für Richtlinien, wenn Thread.Abort angemessen ist. Hier ist das Konzept I implementieren:

  • Selective Ausführung: nur ausgeführt werden, wenn eine vernünftige Erfolgschance (auf die Fähigkeit basiert Timeout oder Wahrscheinlichkeit des Erfolgs Ergebnis im Vergleich zu anderen Warteschlange Produkte gerecht zu werden) besteht. Wenn Sie Code in Segmente und wissen in etwa die erwartete Zeit zwischen Aufgabe Brocken brechen, können Sie vorhersagen, wenn Sie weitere Verarbeitung überspringen sollte. Insgesamt benötigte Zeit kann durch Umwickeln ein Objekt ist Aufgaben mit einer rekursiven Funktion für die Zeitberechnung oder mit einer Controller-Klasse gemessen werden, die Arbeiter wissen erwartete Wartezeiten.
  • Uhren
  • Selective Verwaisung: Nur für die Rückkehr warten, wenn Aussicht auf Erfolg besteht. Indexed Aufgaben werden in einer verwalteten Warteschlange laufen. Aufgaben, die ihre Zeitüberschreitung oder gefährdenden anderen Timeouts übersteigen, werden verwaiste und ein Null-Datensatz wird an ihrer Stelle zurückgeführt. Längere Laufaufgaben können in Asynchron-Anrufe gewickelt werden. Siehe Beispiel asynchroner Aufruf Wrapper: http://www.vbusers.com/codecsharp /codeget.asp?ThreadID=67&PostID=1
  • Bedingte Auswahl: ähnlich wie selektive Ausführung, sondern basierend auf Gruppe statt einzelner Aufgabe. Wenn viele Ihre Aufgaben miteinander verbunden sind, so dass ein Erfolg oder nicht machen zusätzliche Verarbeitung irrelevant, erstellen Sie einen Flag, das überprüft wird, bevor die Ausführung beginnt und wieder vor langen Laufteilaufgaben beginnen. Dies ist besonders nützlich, wenn Sie Parallel.For oder andere solche Warteschlangen Gleichzeitigkeit Aufgaben verwenden.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top