C# 与异步/等待函数流混淆

C# 与异步/等待函数流混淆,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我有以下课程: 数据访问工厂: public class DataAccessFactory { public static IUserAccessLayer User() => new UserAccessLayer(new DataContext()); public static IAuthenticationAccessLayer Authentication() => new AuthenticationAccessLayer(new DataAccess.

我有以下课程:

数据访问工厂:

public class DataAccessFactory
{
    public static IUserAccessLayer User() => new UserAccessLayer(new DataContext());
    public static IAuthenticationAccessLayer Authentication() => new AuthenticationAccessLayer(new DataAccess.DataContext());
}
AuthenticationAccessLayer:

public class AuthenticationAccessLayer : IAuthenticationAccessLayer
{
    private readonly DataContext context;

    public AuthenticationAccessLayer(DataContext context)
    {
        this.context = context;
    }

    public async void RegisterAsync(UserRegisterModel model)
    {
        context.User.Add(new UserModel()
        {
            EmailAddress = model.Email,
            PasswordHash = model.PasswordHash,
            PasswordSalt = model.PasswordSalt
        });
    }

    public async Task<bool> EmailExist(string email)
    {
        var user = await context.User.Where(x => x.EmailAddress.Equals(email)).FirstOrDefaultAsync();
        if (user == null)
            return false;
        else
            return true;
    }
}
用户存储:

public class UserStore : ViewModelBase
{
    public UserStore()
    {
    }

    public UserStore(int userID)
    {
        this.UserID = userID;
    }

    #region Authentication

    public async Task<bool> AuthenticateAsync(LoginModel model)
    {
        return await DataAccessFactory.Authentication().LoginAsync(model);
    }

    public async void RegisterUserAsync(UserRegisterModel model)
    {
        var store = DataAccessFactory.Authentication();

        //check if unique email
        if(await store.EmailExist(model.Email))
            throw new ValidationException($"Email {model.Email} is already registered.");

        store.RegisterAsync(model);
    }

    #endregion

}

我的问题是,在UserStore中的RegisterUserSync函数中,UserRegisterModel是否会在EmailExist函数返回或引发异常之前添加到DB中?

这可能取决于线程调度程序。但是,如果将RegisterUserAsync定义为

    public async Task RegisterUserAsync(UserRegisterModel model)
    {
        var store = DataAccessFactory.Authentication();

        //check if unique email
        if(await store.EmailExist(model.Email))
            throw new ValidationException($"Email {model.Email} is already registered.");

        await store.RegisterAsync(model);
    }

然后RegisterAsync将在EmailExist之后执行。请注意任务返回类型和wait关键字。

如果电子邮件存在,它将抛出ValidateException,因为您正在等待EmailExist函数。

否,您的RegisterUserAsync方法将在EmailExist方法返回后执行

wait运算符应用于异步方法中的任务,以 暂停方法的执行,直到等待的任务完成。 这项任务是正在进行的工作。 ... 等待表达式不会阻止它所在的线程 执行。相反,它会导致编译器注册程序的其余部分 异步方法作为等待的任务的延续。那么控制 返回异步方法的调用方。当任务完成时,它将 调用它的延续,异步方法的执行继续 在它停止的地方


即使该方法是async void RegisterAsync,也无法在EmailExist完成之前运行。RegisterUserAsync只会在完成之前返回,而不会给它的调用方提供一种不知道何时完成的方法。AuthenticationAccessLayer.RegisterAsync实际上不是异步的。context.User.Add没有返回,任务也没有返回…你也应该知道,我想我明白了。等待之后的方法执行被挂起,但线程可以自由执行其他,例如,特定于UI的内容。它将不会在等待后执行,直到EmailExist返回值?