存储库中的异步/等待

本文关键字:等待 异步 存储 | 更新日期: 2023-09-27 18:27:09

如何在存储库中创建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)
    {            
        ...
    }
}

存储库中的异步/等待

只有当你的函数是异步的,并且你期望调用你的函数的客户端是异步的(以及他们的客户端等)时,使用async/await才有用。

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

与自己启动线程相比,这样做的好处是节省了启动新线程和随后进行清理的开销。缺点是,在安排任务时,您不确定线程是否可用。

如果你的函数没有声明为async,你仍然可以使用task.Run(()=>OtherFunction(…))调度任务,但你不能等待它。要等待任务完成,你必须调用task.wait(…)。与此同时,调用你的函数的线程无法继续。如果这个线程是UI线程,你会注意到这一点,因为你的UI没有响应。

因此,如果你想正确使用其他异步函数,最好声明你的函数为async,并返回Task而不是void,返回Task <TResult>而不是TResult。调用另一个异步函数,做其他事情,等待任务返回。客户端需要是异步的,并返回Task/Task <TResult>。唯一可能返回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));
}

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