2017-01-26 41 views
0

我有以下類別:與異步的流動困惑/等待功能

DataAccessFactory:

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

UserStore:

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在RegisterUserAsync函數中,UserRegisterModel會在EmailExist函數返回或拋出異常之前被添加到數據庫中?

+1

'AuthenticationAccessLayer.RegisterAsync'實際上並不是'async'。 'context.User.Add'不會返回,也不會返回'Task' ... –

+0

您還應該[避免異步無效方法](http://haacked.com/archive/2014/11/11/async -void-methods /) – stuartd

回答

2

不,您的RegisterUserAsync方法將在EmailExist方法返回後執行。

msdn

的AWAIT操作者施加到任務中的異步方法 直到等待任務完成暫停該方法的執行。 該任務代表正在進行的工作。
...
等待表達式不會阻止其執行的線程 。相反,它會導致編譯器註冊異步方法的其餘部分,作爲等待任務的延續。控制然後 返回到異步方法的調用者。任務完成後, 將調用其繼續,異步方法的執行將從其中止的地方繼續執行 。

+0

好吧,我想我明白了。 await執行後的方法被掛起,但是線程可以自由地執行其他的,例如,UI特定的東西。直到EmailExist返回一個值後,它纔會在等待之後執行? –

-1

這可能取決於線程調度程序。但是,如果你定義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); 
    } 

然後RegisterAsyncEmailExist後執行。 (請注意任務返回類型和await關鍵字。)

+1

即使方法*是*'async void'' RegisterAsync'仍然無法在'EmailExist'完成之前運行。 'RegisterUserAsync'只會在完成之前返回,而不會給它的調用者(誰沒有顯示)一種知道何時完成的方法。 – Servy

0

如果電子郵件存在,它將拋出ValidateException,因爲您正在等待EmailExist函數。