Avec la logique métier encapsulées derrière synchrone appels de service par exemple .:Stratégies pour appeler le service synchrone appels de manière asynchrone en C#
interface IFooService
{
Foo GetFooById(int id);
int SaveFoo(Foo foo);
}
Quelle est la meilleure façon d'étendre/utiliser ces appels de service de façon asynchrone?
À l'heure actuelle, j'ai créé une classe simple de AsyncUtils:
public static class AsyncUtils
{
public static void Execute<T>(Func<T> asyncFunc)
{
Execute(asyncFunc, null, null);
}
public static void Execute<T>(Func<T> asyncFunc, Action<T> successCallback)
{
Execute(asyncFunc, successCallback, null);
}
public static void Execute<T>(Func<T> asyncFunc, Action<T> successCallback, Action<Exception> failureCallback)
{
ThreadPool.UnsafeQueueUserWorkItem(state => ExecuteAndHandleError(asyncFunc, successCallback, failureCallback), null);
}
private static void ExecuteAndHandleError<T>(Func<T> asyncFunc, Action<T> successCallback, Action<Exception> failureCallback)
{
try
{
T result = asyncFunc();
if (successCallback != null)
{
successCallback(result);
}
}
catch (Exception e)
{
if (failureCallback != null)
{
failureCallback(e);
}
}
}
}
Ce qui me permet d'appeler quoi que ce soit de manière asynchrone:
AsyncUtils(
() => _fooService.SaveFoo(foo),
id => HandleFooSavedSuccessfully(id),
ex => HandleFooSaveError(ex));
Bien que cela fonctionne dans les cas simples d'utilisation, il devient rapidement difficile si d'autres processus besoin de coordonner sur les résultats, par exemple si j'ai besoin d'enregistrer trois objets de manière asynchrone avant que le thread en cours puisse continuer alors je voudrais un moyen d'attendre/rejoindre les threads de travail.
Options J'ai pensé jusqu'à présent comprennent:
- ayant AsyncUtils retour un WaitHandle
- AsyncUtils ayant fait usage d'un AsyncMethodCaller et retourner un IAsyncResult
- réécriture de l'API pour inclure Begin, les appels async End
par exemple quelque chose qui ressemble à:
interface IFooService
{
Foo GetFooById(int id);
IAsyncResult BeginGetFooById(int id);
Foo EndGetFooById(IAsyncResult result);
int SaveFoo(Foo foo);
IAsyncResult BeginSaveFoo(Foo foo);
int EndSaveFoo(IAsyncResult result);
}
Y a-t-il d'autres approches que je devrais envisager? Quels sont les avantages et les pièges potentiels de chacun?
Idéalement, je voudrais garder la couche de service simple/synchrone et fournir quelques méthodes utilitaires faciles à utiliser pour les appeler de manière asynchrone. Je serais intéressé d'entendre parler de solutions et d'idées applicables à C# 3.5 et C# 4 (nous ne l'avons pas encore amélioré mais nous le ferons dans un avenir relativement proche).
Dans l'attente de vos idées.
Pourquoi n'utilisez-vous pas la bibliothèque parallèle de tâches? C'était fait pour ça. http://msdn.microsoft.com/en-us/library/dd460717.aspx –
Ce que Jean dit, mais en particulier, essayez '' Lazy. –
@Steven: Cela devrait être la tâche, pour ce type d'opération. Lazy est pour l'initialisation. –