2016-01-21 23 views
1

我已經實現了基於此Microsoft example的AuthenticateAsync。實現System.Web.Http.Filters.IAuthenticationFilter.AuthenticateAsync()包含對數據庫的阻止調用

按照本例中,AuthenticateAsync()包含

IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken); 

,我已經實現,使通過System.Data.SqlClient.SqlConnection到SQL Server數據庫的呼叫(在I/O阻塞) - 這導致警告

這個異步方法缺少'await'操作符並且會同步運行。

docs說AuthenticateAsync必須返回

任務是進行認證。

我認爲

  • 忽略警告
    • 不是不知道爲什麼微軟宣佈IAuthenticationFilter.AuthenticateAsync 異步。也許IIS想推遲執行?
  • 裹在Task.Run阻塞調用()
    • 難道這雙昂貴的線程數IIS使用?

什麼應該我幹什麼?

阻止AuthenticateAsync內部可以嗎?

回答

1

,我有實施對數據庫的調用(阻塞 I/O) - 導致警告

這種異步方法缺乏「等待」運營商和將同步運行。

這歸結於您的實施AuthenticateAsync。如果您在這裏進行數據庫調用,應該可以在您的實現中使用await運算符,前提是您的Db提供程序支持它(許多包括SqlClient,Entity Framework等的Ado.NET)。在這種情況下,正確的實施就是這樣做。這是解決方案,因爲異步/等待框架然後可以將線程返回到線程池,直到數據庫工作完成,代碼恢復執行。這是在Web框架中運行的I/O調用的首選實現,因爲線程隨後被釋放以服務其他傳入請求,而不是被迫等待I/O完成並實質阻止。

編輯由於您使用SqlClient可以使用異步基於上次編輯

調用這裏等待他們。因此,正確的解決方案是更改AuthenticateAsync的執行方式,在方法實施簽名中保留async關鍵字,並且數據庫調用代碼所生成的await

1

我想說有兩種方法可以解決這個問題。

第一個只是忽略了警告,因爲你自己建議。這將做的唯一的事情是使該方法同步。這將導致IIS堅持昂貴的I/O線程比它更長,但將沒有其他不良影響。

第二種方法是使對數據庫的調用異步並等待其結果。你沒有提到你所連接的數據庫,所以很難說這很容易與否。

如果可能,我會推薦第二個實現。

+0

這是SQL Server數據庫通過System.Data.SqlClient.SqlConnection(更新問題現在) –

+1

在這種情況下,您可以使用SqlCommand的async-methods。 f.x:var reader = await sqlCommand.ExecuteReaderAsync() – Falle1234

+0

https://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlcommand_methods(v = vs.110).aspx – Falle1234

2

SqlConnection和相關類型支持異步操作,所以你應該使用這些。這樣,您不需要任何解決方法,也不會因阻塞而浪費線程。

如果由於某種原因,你真的不能:

忽略警告

一個更好的選擇將是使該方法不async和使用Task.FromResult()創建Task你需要回報。這擺脫了警告,並且也稍微高效。

裹在Task.Run阻塞調用()

難道這雙昂貴的線程數IIS使用?

它不會加倍線程數,await不會阻塞線程,只有你的同步IO會。但是由於調度,同步和上下文切換,它確實會造成一些開銷,所以它並不理想。 Task.FromResult()將是更好的選擇。