C# Task若干問題淺析

Shapley發表於2024-09-29

場景:

分析資料庫的表結構,並將表結構匯出到word中。

方案1.直接用UI執行緒做,由於會造成UI卡頓,忽略。

方案2.用task:

Task ts = Task.Run(() =>
{
    for (int i = 0; i < listTables.Count; i++)
    {
        string name = listTables[i].Name;

        List<SqlserverTableStruct> list = form4DAL.GetTableStruct(name);

        this.Invoke(s, $"{i + 1}/{total}");

        wordUtils.CreateWord(name, list);
    }
});
ts.GetAwaiter().OnCompleted(() =>
{
    wordUtils.SaveFile("c:\\", filename + ".docx");
    this.Invoke(s1, "生成完畢!");
});

方案3:與方案2類似,但最後部分使用:

 ts.ContinueWith(t => {
     wordUtils.SaveFile("c:\\", filename + ".docx");
     this.Invoke(s1, "生成完畢!");
 });

程式碼分析:

方案2和方案3的類似的,但問題的關鍵在於用:OnCompleted和ContinueWith哪個更優?而為了回答這個問題,自己也進行了一些實驗,最終發現了一些有意思的現象:

1.在.net framework框架下:OnCompleted和ContinueWith會隨機出現其中一個先執行,而另一個後執行的情況。

2.在.net 8.0的環境下,始終是continuewith先執行,而complete後執行。

結論:

在新的框架下,這2個的邏輯是:task1執行後,然後判斷是否有continue task,如果有則執行,如果沒有則執行complete。而在老的.net framework框架下,感覺行為有所不同,甚至出現交替優先執行的情況。鑑於此,感覺在老的框架下,儘量避免兩者同時使用(或許是bug).

相關文章