1 回答

TA貢獻(xiàn)1856條經(jīng)驗(yàn) 獲得超5個(gè)贊
這是您修改為 C# 慣用的代碼async
:
請注意以下事項(xiàng):
異步代碼通常是指涉及異步 IO 的操作,其中完成信號(hào)(和后續(xù)完成回調(diào))基本上由硬件中斷和操作系統(tǒng)產(chǎn)生 - 它不應(yīng)與并發(fā)(即多線程)混淆,即使在另一個(gè)線程上運(yùn)行的代碼也可以在概念上被建模為 a
Task
too(實(shí)際上,Task
用于多線程 (Task.Run
) 和 async-IO)。無論如何,重點(diǎn)是:如果您使用的是
async
-IO API(例如SqlDataReader
、FileStream
、NetworkStream
等),那么您可能不想使用Task.Run
.除了必須在 UI 線程中運(yùn)行的代碼(即 WinForms 和 WPF UI 代碼)之外,您應(yīng)該始終使用它
.ConfigureAwait(false)
來允許在可用的后臺(tái)線程中調(diào)用完成回調(diào),這意味著 UI 線程不會(huì)被迫運(yùn)行后臺(tái)代碼.C# 語言設(shè)計(jì)人員意識(shí)到必須發(fā)送垃圾郵件的可怕人體工程學(xué),
.ConfigureAwait(false)
并且正在研究解決方案。一般來說,永遠(yuǎn)不要使用
Task<T>.Result
orTask.Wait()
,因?yàn)樗鼈儠?huì)阻塞線程并引入死鎖的風(fēng)險(xiǎn)(因?yàn)椴荒茉谧枞木€程上運(yùn)行延續(xù)回調(diào))。僅Task<T>.Result
在您驗(yàn)證任務(wù)已完成(或僅執(zhí)行await task
)后使用。您應(yīng)該將 傳遞給您調(diào)用的
CancellationToken
每個(gè)子方法。Async
其他挑剔:
您可以
using()
在同一縮進(jìn)級別組合語句并SqlConnection.OpenAsync
在創(chuàng)建SqlCommand
.camelCase
參數(shù)不應(yīng)該PascalCase
。對實(shí)例成員(字段、方法、屬性等)的引用應(yīng)加上前綴,
this.
以便在視覺上與本地標(biāo)識(shí)符區(qū)分開來。這樣做
if( this.x != null ) this.x.Foo()
并不完全安全,因?yàn)樵诙嗑€程程序x
中,可以在調(diào)用和調(diào)用之間用另一個(gè)值替換。而是使用保留本地參考的操作員來防止地毯從您下方拉出(它的工作原理如下:保證是線程安全的)。if
.Foo()
?.
X lx = this.x; if( lx != null ) lx.Foo()
BindingList
是(可以說)一個(gè) UI 組件,不應(yīng)該像你的FindForLocationAsync
方法那樣從概念上的“背景”函數(shù)返回,所以我返回 aList<T>
,然后 UI 將List<T>
a 包裝在BindingList<T>
.
代碼:
private async void btnSearch_Click(object sender, EventArgs e)
{
this.gridLog.DataSource = null;
this.Cursor = Cursors.WaitCursor;
if (this.btnSearch.Text.ToLower().Contains("load"))
{
this.btnSearch.Text = "Cancel";
this.btnSearch.ForeColor = Color.White;
this.btnSearch.BackColor = Color.Red;
//get params to pass
/* snip */
this.cancellationTokenSource = new CancellationTokenSource();
List<DocLog> list = await DocLog.FindForLocationAsync(docType, subType, days, currLocation.ID, cancellationTokenSource.Token);
gridLog.DataSource = new BindingList<DocLog>( list );
this.btnSearch.Text = "Load Data...";
this.btnSearch.ForeColor = Color.Black;
this.btnSearch.BackColor = Color.FromArgb(225, 225, 225);
}
else
{
CancelSearch();
this.btnSearch.Text = "Load Data...";
this.btnSearch.ForeColor = Color.Black;
this.btnSearch.BackColor = Color.FromArgb(225, 225, 225);
}
this.Cursor = Cursors.Default;
}
private void CancelSearch()
{
this.cancellationTokenSource?.Cancel();
}
public async static Task<List<DocLog>> FindForLocationAsync(string DocType, string SubType, int? LastXDays, Guid LocationID, CancellationToken cancellationToken)
{
List<DocLog> dll = new List<DocLog>();
using (SqlConnection sqlConnection = new SqlConnection(Helper.GetConnectionString()))
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
await sqlConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
sqlCommand.CommandText = (LastXDays == null) ? "DocLogGetAllForLocation" : "DocLogGetAllForLocationLastXDays";
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
sqlCommand.Parameters.Add("@DocType", SqlDbType.NVarChar, 30).Value = DocType.Trim();
sqlCommand.Parameters.Add("@SubType", SqlDbType.NVarChar, 30).Value = SubType.Trim();
sqlCommand.Parameters.Add("@LocationID", SqlDbType.UniqueIdentifier).Value = LocationID;
if (LastXDays != null) { sqlCommand.Parameters.Add("@NumberOfDays", SqlDbType.Int).Value = LastXDays; }
using( SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false) )
{
while (await sqlDataReader.ReadAsync(cancellationToken).ConfigureAwait(false))
{
if (cancellationToken.IsCancellationRequested) break;
DocLog dl = readData(sqlDataReader);
dll.Add(dl);
}
}
}
return dll;
}
- 1 回答
- 0 關(guān)注
- 149 瀏覽
添加回答
舉報(bào)