2016-03-04 5 views
3

J'écris un nouveau code et je voudrais l'écrire en utilisant async et await, mais le code appelant n'est actuellement pas écrit en asynchrone. Est-il correct d'écrire le nouveau code en asynchrone et de l'appeler sync jusqu'à ce que le code appelant prenne en charge async? Ou devrais-je écrire la synchronisation du code, puis le convertir à une date ultérieure? Et serait-ce considéré comme une dette technique?Ecriture d'un nouveau code en asynchrone mais synchro d'appel

public Result Execute(Paramerters parameters) { 
    return ExecuteAsync(parameters).Result; 
} 

public Task<Result> ExecuteAsync(Paramerters parameters) { 
    ... 
} 

Execute est sur une interface et est appelé à partir d'un autre code qui n'est pas encore async. Est-il correct de créer la version asynchrone et de l'appeler de Execute jusqu'à ce que le code appelant Execute soit converti en asynchrone? Mon ancien code est écrit en .net 4.5.1 mais n'est pas encore converti en asynchrone.

+4

Je recommande vivement de rester avec le mantra "Async tout le chemin vers le bas" et mettre à jour le code tout de suite. C'est une bonne lecture sur le sujet: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html Gardez aussi à l'esprit que le "nous réparerons le reste plus tard" "approche est très probablement l'illusion la plus omniprésente dans l'ensemble de l'industrie du développement de logiciels. Ne complétez pas les choses à moitié. Soit rendre le code asynchrone ou non. – David

+5

Cela s'appelle "sync over async" et est un anti-pattern. C'est * généralement * une très mauvaise idée, et certaines combinaisons de sync-over-async ou async-over-sync peuvent * bloquer complètement * ... –

Répondre

3

http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx a quelques bons points sur les deux pourquoi éviter cela, et comment atténuer le problème si vous ne pouvez pas.

Cependant,

Ou devrais-je écrire la synchronisation de code et puis le convertir à une date ultérieure?

Cela est probablement plus facile et permet de contourner complètement le problème.

Et serait-ce considéré comme une dette technique?

Par définition, il est, cependant:

  1. Vous devrez peut-être avoir des appels synchrones à l'avenir de toute façon, pour soutenir ce cas, vous aurez déjà que la dette technique, vous êtes juste traiter avec ça.

  2. Vous avez déjà cette dette technique. Vous avez dit "mais le code appelant n'est pas actuellement écrit en asynchrone". Voilà, c'est votre dette, déjà là. Si les versions synchrone et asynchrone se reflètent (très commun) et que vous placez les méthodes à côté de leurs jumeaux, il peut être facile de faire la plupart des changements à chaque fois en même temps.

0

Selon ce que fait ExecuteAsync, cela fait une différence significative.

On suppose que ExecuteAsync a fait ce qui suit:

public Task<Result> ExecuteAsync(Paramerters parameters) { 
    List<Task> tasks = new List<Task>(); 
    foreach(var param in parameters) 
    { 
     var task = ExecuteSomethingElseAsync(param); 
     tasks.Add(task); 
    } 
    Task.WhenAll(tasks.ToArray()); 
} 

Si l'on suppose ExecutingSomethingelse était IO les D'autres tâches intensives exécuterait sans avoir à attendre la ExecuteSomething méthode autre pour revenir quelque chose pour que pour passer à la suivante param. Si vous deviez le faire de manière synchrone, l'exécution devrait attendre et le temps d'exécution total pourrait être plus lent.

L'appel d'une méthode anyc de manière synchrone peut contenir des avantages si la méthode appelée exécute d'autres méthodes asynchrones.

+0

Mon code fait des appels de base de données –

2

J'ai un article MSDN au sujet de brownfield async development - c'est-à-dire, l'introduction async à une base de code synchrone.Il y a quelques approches différentes, chacune avec ses propres avantages et inconvénients. Ma préférence est d'utiliser le hack argument drapeau, comme tel:

public Result Execute(Parameters parameters) 
{ 
    return ExecuteCoreAsync(parameters, sync: true).GetAwaiter().GetResult(); 
} 

public Task<Result> ExecuteAsync(Parameters parameters) 
{ 
    return ExecuteCoreAsync(parameters, sync: false); 
} 

private async Task<Result> ExecuteCoreAsync(Parameters parameters, bool sync) 
{ 
    if (sync) 
    { 
    Thread.Sleep(2000); // sync implementation 
    return new Result(); 
    } 
    else 
    { 
    await Task.Delay(2000); // async implementation 
    return new Result(); 
    } 
} 

Et oui, si l'opération sous-jacente est naturellement asynchrone, puis une API synchrone est la dette technique.