最近用WPF做金稅盤開發中有這樣一個需求,批量開票每次開票都需要連線一次金稅盤。
比如我有發票 a, b ,c ,d e 這五張發票,每次開具發票都需要呼叫金稅盤底層,才能正常開票。
首先,嘗試寫第一個方法
private void Button_Click(object sender, RoutedEventArgs e)
{
var dateStart = DateTime.Now; //記錄用時的起始時間
DebugText = string.Empty;
List<string> fpList = new List<string>() { "a", "b", "c", "d" }; foreach (var item in MockIO)
{
var dateEnd = DateTime.Now;
var timeSpan = dateEnd - dateStart;//記錄開票用時
DebugText += item + " " + timeSpan.TotalSeconds + "\r\n"; }
} /// <summary>
/// 批量開票方法
/// </summary>
/// <param name="ls"></param>
/// <returns></returns>
public static IEnumerable<string> MockIO(List<string> ls)
{ foreach (var item in ls)
{
Task.Delay(1000).Wait();
yield return item;
Debug.WriteLine(Thread.GetCurrentProcessorId());
}
}
來看效果
很明顯,發生了UI阻塞情況。因為我們並未對程式碼做任何非同步處理。接下來,我們開始嘗試修改。
首先,我們嘗試按照常規非同步方法修改 MockIO 函式,增加 async 關鍵詞,返回結果增加 Task, 內部對IO操作新增 await。
修改完畢後,編譯並沒有通過,VS對該方法報異常
通過提示資訊,我們可以發現,返回值 Task<IEnumerable<string>> 並不是可以迭代的,因為我們採用了 yield 來返回值,所以我們需要一個可以迭代的返回值。
比如改成這樣
但是,這樣一次就返回一組 Task ,沒有用到方便的 yield;
此時,就可以用到 IAsyncEnumerable 來設計了,IAsyncEnumerable是C# 8.0引入的新特性,在非同步迭代中,非常方便。如上述程式碼,可以直接修改為
public static async IAsyncEnumerable<string> MockIOAsync(List<string> ls)
{
foreach (var item in ls)
{
Task<Task<string>> task = Task<Task<string>>.Factory.StartNew(async () =>
{
await Task.Delay(1000);
return item; }); yield return await task.Result;
}
}
我們再執行除錯,看一下效果
我們可以看到,不僅UI沒有被阻塞,同時,傳回的值也是一個接一個的傳過來的,符合我們的預期。
擴充套件:雖然上述步驟我們完成的UI的非阻塞的實現,但是我們整個開票用時並沒有節省。
接下來,我將繼續修改 MockIOAsync 方法,將實現迭代器內部的多執行緒操作。
修改後的程式碼如下
public static async Task<IEnumerable<string>> MockIOPerformanceAsync(List<string> ls)
{
List<string> lss = new List<string>();
List<Task> tasks = new List<Task>();
foreach (var item in ls)
{ Task task = new Task(() =>
{
Task.Delay(1000).Wait();
Debug.WriteLine(Thread.GetCurrentProcessorId());
lss.Add(item);
});
tasks.Add(task);
task.Start(); }
foreach (var item in tasks)
{
await item;
}
return lss;
}
效果展示:
嗯,速度很快,但是排序亂了,因為此方法在遍歷中新建了執行緒,list 新增並不保證按照迭代器的順序新增。有得有失。
自動判斷
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語
自動選擇
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語
有道翻譯
百度翻譯
谷歌翻譯
谷歌翻譯(國內)
翻譯 朗讀 複製 正在查詢,請稍候…… 重試 朗讀 複製 複製 朗讀 複製 via 百度翻譯 譯
自動判斷
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語
自動選擇
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語
有道翻譯
百度翻譯
谷歌翻譯
谷歌翻譯(國內)
翻譯 朗讀 複製 正在查詢,請稍候…… 重試 朗讀 複製 複製 朗讀 複製 via 百度翻譯 譯