Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Async Interface synchronous [duplicate]

Assume i have the following interface:

public interface IApiOutputCache
{
    Task RemoveStartsWithAsync(string key);
    Task<T> Get<T>(string key) where T : class;
    Task RemoveAsync(string key);
    Task<bool> ContainsAsync(string key);
    Task Add(string key, object o, DateTimeOffset expiration, params string[] dependsOnKeys);
    Task<IEnumerable<string>> GetAllKeys();
}

I can implement different cache providers. I implemented it twice for two different caches:

a) azure redis b) memory cache

For azure redis this works absolutely fine since StackExchange.Redis offers all the async methods for me so i can stay completely async.

Now i implement another one for the memory cache which does not offer async api for me. Now what is the best pratice to implement this interface? Implement it as is but just do everything sync? Warp the internal calls to a Task.Run (not a good idea for fast mem cache calls i think).

like image 724
LaurinSt Avatar asked Oct 04 '15 10:10

LaurinSt


People also ask

Does async await make it synchronous?

The async keyword does not make code synchronous. async/await is just a tool to make the syntax for interacting with promises nicer. It's still using promises. "node is asynchronous (meaning multiple lines of code execute at the same time)" that is not what asynchronous means.

Should I expose synchronous wrappers for asynchronous methods?

In my discussion of “async over sync,” I strongly suggested that if you have an API which internally is implemented synchronously, you should not expose an asynchronous counterpart that simply wraps the synchronous method in Task. Run.

Can we call asynchronous method from another synchronous method in C#?

Use the Result property on the asynchronous Task, like so: // Synchronous method. void Method()

Can I use async in interface?

Interfaces can't use async in a method declaration, simply because there is no need. If an interface requires that a method returns Task , the implementation may choose to use async , but whether it does or not is a choice for the implementing method.


1 Answers

Forget about Task.Run, there's no need to offload anything to the ThreadPool.

Implement everything synchronously and return an already completed Task with Task.FromResult when returning a value and Task.CompletedTask when not:

Task<T> GetAsync<T>(string key)
{
    T result = Get(key);
    return Task.FromResult(result);
}

Task RemoveAsync(string key)
{
    Remove(key);
    return Task.CompletedTask;
}

Or even better, since it's a cache you can cache the tasks themselves instead of the results and return the same task object every time.

like image 56
i3arnon Avatar answered Sep 28 '22 08:09

i3arnon