简体   繁体   中英

Writing new code in async but calling sync

I am writing some new code and would like to write it using async and await, but the calling code is not currently written in async. Is it right to write the new code in async and call it sync until the calling code supports async?

Or should I write the code sync and then convert it at a later date? And would it be considered technical debt?

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

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

Execute is on an interface and is called from some other code that is not yet async. Is it correct to create the async version and call it from Execute until the code calling Execute is converted to async? My old code is written in .net 4.5.1 but is not yet converted to async.

http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx has some good points on both why to avoid this, and how to alleviate the problem if you can't.

However,

Or should I write the code sync and then convert it at a later date?

That's likely easier, and does get away from the issue entirely.

And would it be considered technical debt?

By definition it is, though:

  1. You may need to have synchronous calls well into the future anyway, to support that case, so you will already have that technical debt, you're just dealing with it.

  2. You do have that technical debt already. You said, "but the calling code is not currently written in async". There, that's your debt, already there.

  3. If the sync and async versions mirror each other (very common) and you place the methods next to their twins, it can be easy to do most changes to each at the same time.

I have an MSDN article on the subject of brownfield async development - that is, introducing async to a synchronous codebase. There's a few different approaches, each with their own pros and cons. My preference is to use the flag argument hack, as such:

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

And yes, if the underlying operation is naturally asynchronous, then a synchronous API is technical debt.

Depending on what ExecuteAsync does it does make a significant difference.

Suppose ExecuteAsync did the following:

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

Assuming ExecutingSomethingelse was IO intensive the other tasks would execute without having to waiting for the ExecuteSomething else method to return something in order for it to move onto the next param. If you were to do this synchronously, the execute would have to wait and total execution time could be slower.

Calling an anyc method synchronously could contain some benifits if the method being called, executes other async methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM