2013-02-11 2 views
1

J'ai une application .NET 2.0. Dans cette application, j'ai besoin de transmettre des données à mon serveur. Le serveur expose une URL REST à laquelle je peux envoyer des données. Lorsque je renvoie des données à mon serveur, je dois parfois le faire de manière asynchrone et d'autres fois, j'ai besoin d'un appel bloquant. Dans le scénario de l'appel asynchrone, j'ai besoin de savoir quand l'appel est terminé. Tout jusqu'à ce point, je comprends comment faire.Appel asynchrone avec une méthode statique en C# .NET 2.0

Lorsque j'ai des problèmes, la méthode sur laquelle je travaille DOIT être statique. C'est le code dont j'ai hérité, et je préfère ne pas avoir à refaire tout ce code. À l'heure actuelle, j'ai deux méthodes statiques:

public static string SendData (...) { 
} 

public static string SendDataAsync(...) { 

} 

Le string renvoyé est un code de réponse du serveur. La partie statique me donne des ajustements. Cela ne cause pas de problème dans ma version de blocage. Cependant, dans le concours de l'appel asynchrone, je ne sais pas quoi faire.

Quelqu'un a-t-il des idées qu'il peut fournir?

+1

wrap Juste l'appel de blocage dans un délégué et d'utiliser son async mécanisme. – leppie

+0

Vous devrez changer la signature de votre méthode statique. Vous devrez soit renvoyer un objet qui indiquera quand l'opération est effectuée et contenir le résultat (c'est-à-dire IAsyncResult'), transmettre un délégué de rappel, exposer un événement statique ou autre chose. Vous ne serez pas en mesure d'exposer la chaîne directement, sauf si vous bloquez, auquel cas ce n'est pas asynchrone. – Servy

+0

@Servy pouvez-vous montrer du code en référence à ce que vous voulez dire? Si c'est ce que cela ressemble, je voudrais vous donner le crédit pour la réponse. –

Répondre

0

Il s'agit du modèle asynchrone général avant C# 5 (IIRC).

public static string SendData (...) { 
} 

public static IAsyncResult BeginSendData(..., AsyncCallback cb) { 
    var f = new Func<..., string>(SendData); 
    return f.BeginInvoke(..., cb, f); 
} 

public static string EndSendData(IAsyncResult ar) { 
    return ((Func<..., string>) ar.AsyncState).EndInvoke(ar); 
} 

Utilisation:

BeginSendData(..., ar => 
    { 
    var result = EndSendData(ar); 
    // do something with result 
    }); 

exemple de la console complète:

public static string SendData(int i) 
{ 
    // sample payload 
    Thread.Sleep(i); 
    return i.ToString(); 
} 

public static IAsyncResult BeginSendData(int i, AsyncCallback cb) 
{ 
    var f = new Func<int, string>(SendData); 
    return f.BeginInvoke(i, cb, f); 
} 

public static string EndSendData(IAsyncResult ar) 
{ 
    return ((Func<int, string>)ar.AsyncState).EndInvoke(ar); 
} 

static void Main(string[] args) 
{ 
    BeginSendData(2000, ar => 
     { 
      var result = EndSendData(ar); 
      Console.WriteLine("Done: {0}", result); 
     }); 

    Console.WriteLine("Waiting"); 
    Console.ReadLine(); 
} 

L'impression de volonté ci-dessus:

Waiting 
Done: 2000 
0

Créez une classe enveloppant vos appels de service. De cela, appelez uniquement la méthode de blocage statique, mais appelez-le à partir d'un thread d'arrière-plan. Exécutez ensuite un rappel ou déclencher un événement, une fois l'appel de service retourné:

public class CompletedEventArgs : EventArgs 
{ 
    public string Result { get; set; } 
} 

public class MyServiceWrapper 
{ 
    public event EventHandler<CompletedEventArgs> CallCompleted; 

    public string SendData() 
    { 
     return StaticService.SendData(); 
    } 

    public void SendDataAsync() 
    { 
     ThreadPool.QueueUserWorkItem(state => { 
      var result = StaticService.SendData(); 
      var handler = CallCompleted; 
      if (handler != null) 
      { 
       handler(this, new CompletedEventArgs{ Result = result }); 
      } 
     }); 
    } 
} 

Gardez à l'esprit que l'événement qui est soulevée ne vient pas de la thread d'interface utilisateur, ainsi vous devez l'expédier en conséquence quand vous voulez réagir dans une interface utilisateur.

+0

Je proposais une méthode plus élégante que celle-ci! Voir 'Delegate.BeginInvoke' et' Delegate.EndInvoke'. – leppie

+0

@leppie Désolé, je vous ai mal compris (référence supprimée à votre commentaire) – Spontifixus

Questions connexes