《C#併發編程經典實例》學習筆記—2.3 報告任務

問題

異步操作時,需要展示該操作的進度

解決方案

IProgress<T> InterfaceProgress<T> Class

插一段話:讀《C#併發編程經典實例》這本書偶有困惑,深感書中內容過於精煉,或許是作者故意爲之,但顯然對我這般知識淺薄的人來說,讀起來這本書感到晦澀。偶然找到作者的個人博客,看到作者博客中對某一個知識點不同時間點上由淺至深的研究,十分欣喜。作者個人博客地址:https://blog.stephencleary.com/

可查看此書作者博客中相關Progress的文章Reporting Progress from Async Tasks瞭解更多一手知識

文中作者多次提到UI線程,很困惑,因爲最近幾年基本沒在工作中寫WPF、WebForm或者WinForm,所以作者說UI線程時很困惑,將其帶入WPF、WebForm或者WinForm的使用場景,就好理解了。

不在廢話,上文中僞代碼例子

static async Task MyMethodAsync(IProgress<double> progress = null)
{
	double percentComplete = 0;
	while (!done)
	{
		...
		if (progress != null)
		progress.Report(percentComplete);
	}
}

Progress只有一個Report方法,Report報告進度更改

static async Task CallMyMethodAsync()
{
	var progress = new Progress<double>();
	progress.ProgressChanged += (sender, args) =>
	{
		...
	};
	await MyMethodAsync(progress);
}

注意

  1. IProgress<T>參數可以爲空,這意味着該異步操作不需要報告更改進度。
  2. Report方法可以是異步的,這樣的話,MyMethodAsync執行過程中,可能Report方法還未執行,進度還沒有被更新。這樣的話,T最好是一個不可變類型,值類型最好,如果T非要使用可變類型,最好每次Copy一個副本。
  3. 如果一個方法可以報告進度,最好也應該可以被取消。
  4. Progress 會在創建時捕獲當前上下文,並且在這個上下文中調用回調函數。這意味着,如果在 UI 線程中創建了 Progress ,就能在 Progress 的回調函數中更新 UI,即使異步方法是在後臺線程中調用 Report 的。

關於如何使用進度,並可以取消該方法的文章,可查看4.5 中的異步: 啓用進度和異步 Api 中的取消

異常

Progress<T>.ProgressChanged不會拋出異常,或者說它拋出的異常會直接拋給上下文context

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章