2009-09-09 3 views
1

J'essaie de comprendre comment utiliser le type de délégué d'action pour forcer un délai d'expiration lorsque des méthodes appelées dans une DLL COM tierce se bloquent. Après beaucoup de recherches, je trouve que je peux utiliser l'action <> ou Func <> et transmettre jusqu'à 4 paramètres génériques selon que la méthode appelée renvoie un paramètre ou non.Mise en œuvre du délai d'appel de la fonction générique avec les paramètres

Pour cette instance, je souhaite appeler un délai d'attente sur une série de méthodes qui renvoient void et prennent 2 paramètres. Ce qui suit est le code que je mets ensemble, mais je suis incapable de déterminer comment coder correctement le BeginInvoke, je suis invité à placer "T arg1" et "T arg2" mais quand j'entre param1 ou param2 VS2008 me dit que ces les valeurs sont indéterminées.

est ici le code tel qu'il est à ce jour:

static void CallAndWait(Action<T, T> action, int timeout) 
{ 
    Thread subThread = null; 
    Action<T, T> wrappedAction = (param1, param2) => 
    { 
     subThread = Thread.CurrentThread; 
     action(param1, param2); 
    }; 

    IAsyncResult result = wrappedAction.BeginInvoke(param1, param2, null, null); 
    if (((timeout != -1) && !result.IsCompleted) && 
    (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted)) 
    { 
     if (subThread != null) 
     { 
      subThread.Abort(); 
     } 

     //TODO: close external resource. 

     throw new TimeoutException(); 
    } 
    else 
    { 
     action.EndInvoke(result); 
    } 
} 

Toutes les idées sur ce qui ne va pas ici serait très apprécié.

Voici un réédités code basé sur le premier commentaire

Merci pour l'entrée jusqu'à présent. Les compilations suivantes. Je ne peux pas sembler avoir la syntaxe juste pour l'appeler.

public static void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout) 
{ 
    Thread subThread = null; 
    T1 param1 = default(T1); 
    T2 param2 = default(T2); 

    Action<T1, T2> wrappedAction = (p1, p2) => 
    { 
     subThread = Thread.CurrentThread; 
     action(param1, param2); 
    }; 

    IAsyncResult result = wrappedAction.BeginInvoke(param1, param2, null, null); 
    if (((timeout != -1) && !result.IsCompleted) && 
    (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted)) 
    { 
     if (subThread != null) 
     { 
      subThread.Abort(); 
     } 

     //TODO: close external resource. 

     throw new TimeoutException(); 
    } 
    else 
    { 
     action.EndInvoke(result); 
    } 
} 

Je suis en train de tester en appelant la méthode suivante avec elle:

public void LongTimeProcess(int a, string b) 
{ 
    Thread.Sleep(a); 
} 

Mais le code suivant est incorrect:

Action<int, string> action = (s1, s2) => LongTimeProcess(s1, s2); 
    CallAndWait<int, string>(action(1500, "hello"), 500); 

code mis à jour I » J'ai posté le code pour référence future par les utilisateurs du forum. Le code ci-dessous semble fonctionner. Le seul point à vérifier est que mon test d'unité provoque une exception lors de l'appel de la routine une seconde fois sur la même fonction au point où nous "action.EndInvoke (résultat)" comme le résultat n'est pas associé à l'action . C'est probablement parce que mon LongProcess est juste un Thread.sleep, qui dans ce cas signifiera qu'il n'a pas avorté au moment où mon deuxième appel est fait.

public static void CallAndWait<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2, int timeout) 

    { 
     Thread subThread = null; 
     Action<T1, T2> wrappedAction = (p1, p2) => 
     { 
      subThread = Thread.CurrentThread; 
      action(arg1, arg2); 
     }; 

     IAsyncResult result = wrappedAction.BeginInvoke(arg1, arg2, null, null); 
     if (((timeout != -1) && !result.IsCompleted) && 
     (!result.AsyncWaitHandle.WaitOne(timeout, false) || !result.IsCompleted)) 
     { 
      if (subThread != null) 
      { 
       subThread.Abort(); 
      } 

      //TODO: close external resource. 

      throw new TimeoutException(); 
     } 
     else 
     { 
      action.EndInvoke(result); 
     } 
    } 
+0

J'ai trouvé votre erreur et j'ai mis à jour ma réponse. –

+0

voir: http://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout –

Répondre

1

Au début, il devrait probablement être

static void CallAndWait<T>(Action<T, T> action, int timeout) 

au lieu de

static void CallAndWait(Action<T, T> action, int timeout) 

et si les paramètres ont différents types, même ce qui suit.

static void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout) 

Mais je ne pense pas que ce soit tout. Je vais le regarder encore.

MISE À JOUR

Maintenant, je peux voir votre problème ... vous appelez l'action lorsque vous essayez d'appeler CallAndWait(). L'appel doit être le suivant

CallWithTimeout.CallAndWait(action, 1500, "hello", 500); 

au lieu de votre appel.

CallWithTimeout.CallAndWait<int, string>(action(1500, "hello"), 500); 

Donc, vous devez changer la signature de la méthode de

void CallAndWait<T1, T2>(Action<T1, T2> action, int timeout) 

à

void CallAndWait<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2, int timeout) 

modifier le corps un peu et vous devriez être fait.

+0

Ah, d'accord. Cela a du sens et me donne quelque chose à regarder plus loin. – ChrisBD

+0

Merci, cela a fonctionné un régal. – ChrisBD