Tip 4: Async Library Methods Shouldn't Lie

Play Tip 4: Async Library Methods Shouldn't Lie
Sign in to queue


Libraries shouldn't lie. That's not why they're called "lie-braries"...

The threadpool is an app-global resource, so you should leave the callers of your library to decide how and when they want to use it. Your library methods should not use the threadpool (Task.Run, Parallel.For, ...) internally in secret. Most of the time, they should have async signatures if and only if their internal implementations are truly async.

Slides, source code and transcript for this video are available here.

Generic Episode Image

Sometimes you're forced to write a synchronous blocking method to fit into an older synchronous framework, but you still want to call new async APIs. There's no good answer here. People use Task.Wait() or Task.Result, which are bad solutions. Stephen Toub lists some less bad solutions here.

Sometimes you're trying to work in a modern asynchronous framework but you have to call legacy synchronous APIs. People use Task.Run here, but you should understand that there's simply no way to gain the scalability of async. For that you really need async all the way down. Once again, Stephen Toub fleshes out what to do here.



The Discussion

  • User profile image

    Love this guy. There's more tips if you click Lucian's name.



  • User profile image

    Hi Lucian,

    I have experienced many frustrations trying to learn how to cope when sync and async worlds collide. Thanks to your educational blog-videos about async patterns and pitfalls I am starting to get a handle on the issues.

    I currently have a slight twist on meshing the synchronous and asynchronous worlds, hopefully you can provide some insight. There is an interface to a repository (IRepository ) that mostly defines CRUD operations to persist POCO models. Two actual IRepository implementations save data to a local database and the Azure table storage (either of which may take a while to handle operations), so it seems sensible for the IRepository interface definition to include async methods that return Tasks, for example:

    public interface IRepository
    Task<TModel> ReadAsync<TModel>(int primaryKey) where TModel : IPrimaryKey, new();
    Task DeleteAsync<TModel>(int primaryKey) where TModel : IPrimaryKey, new();
    Task<int> InsertAsync<TModel>(TModel model) where TModel : IPrimaryKey, new();
    // ... etc ...

    As usual, an instance of a class implementing IRepository is injected into my View Models, like:

    public class MyViewModel
    private IRepository _repository;
    public MyViewModel(IRepository repository)
    _repository = repository;
    protected async Task LoadFromKeyAsync(int primaryKey)
    MyPocoModel model = await _repository.ReadAsync<MyPocoModel>(primaryKey);
    // ... assimilate model info...
    // view model stuff, including an async event handler that calls LoadFromKeyAsync...


    But now a situation has arisen where I need an implementation of an IRepository using in-memory data structures like a dictionary. The API for adding and reading stuff from a Dictionary consists of synchronous methods, but the IRepository interfacedefinition has async bias. So, am I being stupid by wrapping the synchronous dictionary methods using returnTask.FromResult<T>() to fulfill the IRepositorysignature requirements? For example:


    public class DictRepository : IRepository
    Dictionary<Type, object> _dict; 
    public DictRepository()
    _dict = new Dictionary<Type, object>();
    public Task<int> InsertAsync<TModel>(TModel model) where TModel : IPrimaryKey, new()
    // simplified for the sake of example...
    MockDbTable<TModel> mockDbTable = (MockDbTable<TModel>)(_dict[typeof(TModel)]);
    model.PK = mockDbTable.Keys.Max() + 1;
    mockDbTable.Add(model.PK, model);
    return Task.FromResult<int>(model.PK);
    // ...


    If this is a not a good idea, can you provide guidance on what to do when an interface contract you need to fulfill is async, but the specific implementation is based on synchronous methods? (of course the converse issue could also arise...)

    Thank you for your insight,


  • User profile image


    I'm confused about one of the "bad" uses of async and the Task-Based Asynchronous Pattern example provided here : https://msdn.microsoft.com/en-us/library/ms734701(v=vs.110).aspx

    Is it ok to do this on server side?
    I really enjoyed your Async tips, thank you.

  • User profile image

    @squizfloats - You've got the right idea. This is a situation where the overall API design is forcing you to have an async signature, even though your method itself isn't async in its implementation.

    Please watch the next video in the series. That discusses EXACTLY this case. Actually it discusses it in the guise of "MemoryStream". Obviously Stream has to have async APIs since most streams (disk, network, ...) are asynchronous in nature. But when you come to implement MemoryStream, it has no natural async implementation. And so it uses Task.FromResult exactly as you described.

    The video talks about several useful micro-optimizations specifically for this case. Worth considering.

  • User profile image

    @Joao, thanks for the pointer. I think that MSDN page has poor guidance. I'll contact the authors of it.

  • User profile image

    I found Lucian the most knowledgeable on Async programming style. His code samples, presentation and knowledge...all top grades, awesome talk!

Add Your 2 Cents