Question

comment définir un délai d'attente pour une méthode occupée + C #.

Était-ce utile?

La solution

Ok, voici la vraie réponse.

...

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.
  }
}

   ...

Ceci combine deux des parties les plus amusantes de l’utilisation de C #. Tout d'abord, pour appeler la méthode de façon asynchrone, utilisez un délégué doté de la magie fancy-pants BeginInvoke .

Ensuite, utilisez un moniteur pour envoyer un message du LongRunningMethod au ImpatientMethod pour lui faire savoir quand c'est fait ou s'il n'en a pas entendu parler. dans un certain laps de temps, il suffit d'abandonner.

(p.s.- Je plaisante en disant que c'est la vraie réponse. Je sais qu'il y a 2 ^ 9303 façons de traiter un chat. Surtout en .Net)

Autres conseils

Vous ne pouvez pas faire cela, à moins de changer de méthode.

Il y a deux façons:

  1. La méthode est construite de telle sorte qu'elle mesure elle-même sa durée d'exécution, puis renvoie prématurément si elle dépasse un certain seuil.
  2. La méthode est construite de telle sorte qu'elle surveille une variable / un événement qui indique "lorsque cette variable est définie, quittez", puis vous avez un autre thread qui mesure le temps passé dans la première méthode, puis définissez cette variable lorsque le temps écoulé a dépassé un certain seuil.

La réponse la plus évidente, mais malheureusement fausse, que vous pouvez obtenir ici est "Il suffit d’exécuter la méthode dans un fil de discussion et d’utiliser Thread.Abort quand elle a été exécutée trop longtemps".

Le seul moyen correct consiste pour la méthode à coopérer de manière à permettre une sortie en mode minimal lorsqu'elle fonctionne trop longtemps.

Il existe également une troisième méthode, dans laquelle vous exécutez la méthode sur un thread séparé, mais après avoir attendu qu'elle se termine, et cela prend trop de temps pour le faire, vous dites simplement: "Je ne vais pas attendre que cela se produise." terminer, mais juste le jeter ". Dans ce cas, la méthode sera toujours exécutée et finira par se terminer, mais cet autre thread qui l'attendait abandonnera tout simplement.

Pensez à la troisième façon d’appeler quelqu'un et de lui demander de chercher le livre que vous lui avez prêté dans sa maison. Après une attente de 5 minutes, vous dites simplement: "ah, jette-le", et Raccrocher. Finalement, cette autre personne trouvera le livre et reviendra au téléphone, pour s'apercevoir que vous ne vous souciez plus du résultat.

Bien que la réponse de MojoFilter soit bien cela peut provoquer des fuites si le " LongMethod " se fige. Vous devez ABANDONNER l'opération si le résultat ne vous intéresse plus.

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();
}

C’est une vieille question, mais la solution la plus simple qui n’est plus disponible alors: tâches!

Voici un exemple de code:

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

Vous pouvez exécuter la méthode dans un thread séparé, la surveiller et la forcer à quitter si elle fonctionne trop longtemps. Un bon moyen, si vous pouvez l'appeler ainsi, serait de développer un attribut pour la méthode dans Post Sharp afin que le code de surveillance ne soit pas incrusté dans votre application.

J'ai écrit ce qui suit comme exemple de code (remarque: la partie exemple de code, cela fonctionne, mais le multithreading risque de poser problème, ou si la méthode en question capture l'exception ThreadAbortException, cela résoudrait le problème):

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();
}

Avec l'invocation suivante:

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

Je dois travailler sur la lisibilité de mon code.

Les méthodes n'ont pas de délai d'expiration en C #, à moins que votre dans le débogueur ou le système d'exploitation ne croie que votre application est "suspendue". Même dans ce cas, le traitement continue et si vous ne détruisez pas l'application, une réponse est renvoyée et l'application continue de fonctionner.

Les appels vers des bases de données peuvent avoir des délais.

Pourriez-vous créer une méthode asynchrone afin de poursuivre votre travail d’autres choses pendant que vous êtes "occupé" méthode se termine?

J'écris régulièrement des applications pour lesquelles je dois synchroniser des tâches critiques sur différentes plateformes. Si vous pouvez éviter thread.abort, vous devriez le faire. Voir http: // blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a- timeout.aspx et http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation pour savoir quand thread.abort est approprié. Voici le concept que je mets en œuvre:

  • Exécution sélective: exécutée uniquement s'il existe une chance raisonnable de succès (en fonction de la capacité à respecter le délai d'expiration ou la probabilité de réussite par rapport aux autres éléments en file d'attente). Si vous divisez le code en segments et que vous connaissez à peu près le temps prévu entre les tâches, vous pouvez prédire si vous devez ignorer tout traitement ultérieur. Le temps total peut être mesuré en encapsulant une tâche de corbeille d’objets avec une fonction récursive pour le calcul du temps ou en disposant d’une classe de contrôleur surveillant les travailleurs pour connaître les temps d’attente attendus.
  • Orphelin sélectif: n'attendez le retour que s'il existe une chance raisonnable de succès. Les tâches indexées sont exécutées dans une file d'attente gérée. Les tâches qui dépassent leur délai d'attente ou qui risquent de provoquer d'autres délais d'attente sont orphelines et un enregistrement null est renvoyé à leur place. Les tâches plus longues peuvent être encapsulées dans des appels asynchrones. Voir un exemple d'appel asynchrone: http://www.vbusers.com/codecsharp /codeget.asp?ThreadID=67&PostID=1
  • Sélection conditionnelle: similaire à l'exécution sélective, mais basée sur un groupe plutôt que sur une tâche individuelle. Si plusieurs de vos tâches sont interconnectées, de sorte qu'un succès ou un échec rend le traitement supplémentaire inutile, créez un indicateur vérifié avant le début de l'exécution et avant le début des sous-tâches à exécution longue. Ceci est particulièrement utile lorsque vous utilisez parallel.for ou d’autres tâches de ce type en concurrence.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top