Reputation: 24619
How can I make async/await method in repository? Should I use Task.Run?
public virtual void Add(T entity)
{
try
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_context.Entry(entity);
Entities.Add(entity);
}
catch (DbEntityValidationException dbEx)
{
...
}
}
Upvotes: 3
Views: 2088
Reputation: 30512
Using async/await is only useful if your function is async and you expect that the clients that call your functions are async (and their clients etc).
The reason is, because calling an async function does not mean that the function is performed. It means that a Task is scheduled to run the function performed by a thread in a pool of available threads. After the task is scheduled your function can continue with the next statement. When it needs the result of the scheduled task it awaits until the scheduled task is finished.
The advantage above starting a thread yourself is that this saves the overhead to start a new thread and do the cleanup afterwards. The disadvantage is that you are not certain that a thread is available the moment you schedule the task.
If your function is not declared async you still can schedule a task using Task.Run( () => OtherFunction(...)), but you can't await for it. To wait for the task to finish you have to call Task.Wait(...). In the meantime the thread that called your function can't continue. If this thread is the UI thread you'll notice this because your UI is not responsive.
So if you want to make proper use of other async functions, its best to declare your function async and return Task instead of void and Task<TResult
> instead of TResult. Call the other async function, do other things and await the task before returning. The clients need to be async and return Task / Task<TResult
>. The only async client that may return void is the event handler.
Example:
public async void button1_clicked(object sender, ...)
{
Task<int> task1 = this.DoSomethingAsync(...);
// while task1 is running you can do other things
// you can even schedule another task:
Task task2 = this.DoSomethingElseAsync(...);
// do other things. After a while you need the result of task1:
int task1Result = await task1;
// or if you want to await until both tasks are finished:
await Task.WhenAll(new Task[]{task1, task2});
int task1Result = task1.Result;
}
private async Task<int> DoSomethingAsync(...)
{
// schedule another async task and await:
await DoSomethingElseAsync(...);
return 42;
}
private async Task DoSomethingElseAsync(...)
{
// do something really important:
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
}
If you don't want to force your clients to be async, consider creating two versions, one async and one non-async. This is quite common. See definitions in Files, Streams, DbConnections etc.
Upvotes: 2