存储库中的异步/等待

时间:2015-12-16 10:09:45

标签: c# asynchronous asp.net-web-api

如何在存储库中创建async / await方法?我应该使用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)
    {            
        ...
    }
}

1 个答案:

答案 0 :(得分:1)

使用async / await仅在函数是异步的情况下才有用,并且您希望调用函数的客户端是异步的(以及它们的客户端等)。

原因是,因为调用异步函数并不意味着执行该函数。这意味着任务被安排运行由可用线程池中的线程执行的功能。在安排任务后,您的函数可以继续下一个语句。当需要计划任务的结果时,它等待计划任务完成。

上面开始一个线程的优点是,这可以节省开始新线程的开销,并在之后进行清理。缺点是您在安排任务时不确定线程​​是否可用。

如果您的函数未声明为异步,您仍然可以使用Task.Run(()=> OtherFunction(...))安排任务,但您无法等待它。要等待任务完成,您必须调用Task.Wait(...)。与此同时,调用函数的线程无法继续。如果此线程是UI线程,您会注意到这一点,因为您的UI没有响应。

因此,如果您想正确使用其他异步函数,最好将函数声明为异步并返回Task而不是void和Task <TResult&gt;而不是TResult。在返回之前调用另一个异步函数,执行其他操作并等待任务。客户端需要异步并返回任务/任务<TResult&gt;。可能返回void的唯一异步客户端是事件处理程序。

示例:

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

如果您不想强制客户端异步,请考虑创建两个版本,一个是异步,另一个是非异步。这很常见。请参阅文件,流,Db连接等中的定义。