主頁 > 移動端開發 > F#中Async.Sequantial的任務版本是什么

F#中Async.Sequantial的任務版本是什么

2022-09-16 01:47:56 移動端開發

下面的代碼曾經可以作業 - 但我正在將我的很多 async{} 函式轉換為 task{} 并且我無法弄清楚如何在沒有可變變數的情況下使其按順序運行。

let processBatchTransaction(page: IPage, 
                            bnzBatch: BNZBatch, 
                            cardTransactionswithOrder: BNZCardWithOrder list,
                            xeroClient: XeroClientFull) : Task<StatusMessage> = task {
    let matchedTransactionsSeq 
        = seq{
                for cardTransactionWithOrder in cardTransactionswithOrder do
                    let matchedTransaction = matchTransaction(page,bnzBatch,cardTransactionWithOrder, xeroClient)
                    yield matchedTransaction
        }

    let! matchedTransactions = matchedTransactionsSeq |> Async.Sequential
.... etc
}

函式“matchTransaction”曾經是異步的——但沒有Task.Sequential,只有Task.WhenAll,但我需要它們一個接一個地同步運行。

uj5u.com熱心網友回復:

編輯:請參閱下面的所有方式,以獲得更簡單、更慣用的解決方案。該行下方的原始答案。


正如所承諾的(盡管布賴恩已經給出了很好的答案),這是我的。讓我們首先了解一些規則:

  • 創建的任務task { ... }將始終是熱啟動的。這意味著它會立即在當前執行緒(或后臺執行緒,如果您使用backgroundTask)上運行。
  • 通過 TPL 創建的帶有Task<_>類的任務將始終延遲啟動。就像async你必須手動啟動這些一樣。
  • task在CE中系結任何任務都將啟動該任務。
  • 下一個系結運算式只會在前一個系結運算式完成后開始。

這意味著,給定一個帶有Tasks 的陣列或序列,它們很可能在你得到它們時已經在運行。而且由于它們不是通過創建的bind,它們將異步運行。為了防止這種情況,我們需要一些規則。

編輯:如果您還沒有,請查看F# ,它可以開箱即用地執行以下操作。

規則 0:處理任務時,總是回傳一個task

組合任務、系結任務或加入任務時,始終將結果回傳為task. 這將簡化您的整體流程,此外,您不能在不阻塞執行緒的情況下回傳非任務(或非異步)。

規則 1:延遲你的任務

Brian 建議通過lazy. 這可以。您也可以簡單地使用單位函式:fun() -> task { dosomething }.

規則 2:不要使用.Resultor.Wait()

這些會阻塞你的執行緒。

規則 3:不要使用類似的東西List.traverseTaskResultA

這些函式是其他優秀FsToolkit.ErrorHandling.TaskResult庫的一部分,不會像run X -> wait for result -> run Y -> wait for result. 相反,他們做到了run X -> run Y -> run Z -> asTask

換句話說,那些庫函式會導致異步的、重疊的執行。

規則 4:不要使用Thread.Sleep

幾乎沒有規則,但是當我測驗你的場景時,我使用了Thread.Sleep. 問題是,這個函式阻塞了當前執行緒。它會給人一種錯誤的印象,即您的函式在您的測驗場景中按順序運行,但在您的實際場景中它們不再如此。

改為使用Task.Delay它的作業原理相同,但不會阻塞執行緒。

解決方案

有多種方法可以做到這一點。我將只向您展示一個使用ContinueWith. 腳步:

  • 您的任務必須延遲回傳,作為單元函式
  • 您的任務不依賴于彼此的結果(但這很容易改變)
  • 將您的任務包裝在一個延續中,然后Unwrap再次延續。

最后一個似乎有點奇怪,但 TPL 沒有附帶標準的bind. bind來自 F# 的雖然適用于此,但使用起來有點困難。Ply庫帶有一個更簡單的系結,您也可以嘗試一下。

無論如何,這是硬核方式,僅使用標準庫函式。好訊息是,您只需撰寫一次此函式。

/// Join multiple delayed tasks and return the result of the last
let join tasks =
    let wrapNext (t: unit -> Task<_>) (source: unit -> Task<_>): unit -> Task<_> =
        fun () ->
            source()
                // this is the CORE of the whole operation
                .ContinueWith((fun (_: Task) -> t ()), TaskContinuationOptions.OnlyOnRanToCompletion)
                // extra step needed, as BCL has no direct way to unwrap nested tasks
                .Unwrap() :?> Task<_>

    let rec combine acc (tasks: (unit -> Task<_>) list) =
        match tasks with
        | [] -> acc
        | t :: tail -> combine (wrapNext t acc) tail

    match tasks with
    | first :: rest -> combine first rest
    | [] -> failwith "oh oh, no tasks given!"

這是您可以使用它的方法。第一個函式看起來有點笨拙,但它只是為了模仿您的場景并能夠仔細檢查它是否按順序運行。

/// Create 10 tasks, use stream for writing, otherwise would garble FSI
/// Note that those can be task or backgroundTask
let createBunchOfTasks(sw: StreamWriter) =
    let mutable x = 0
    let rnd () = Random().Next(10, 30)
    let o = obj ()

    let runTask i = backgroundTask {
        let! _ = Task.Delay(rnd ())  // use randomization to ensure tasks last different times
        x <- x   1

        // just some logging to a file, stdout is not good in this case
        lock o (fun () -> sw.WriteLine(sprintf "Task #%i after delay: %i" i x))
        return x
    }

    [
        // creating bunch of dummy tasks
        for i in 0..10 do
            fun () -> runTask i
    ]

在您的場景中,您不需要上面的代碼,但您需要類似的東西來呼叫該join函式。如果你需要記錄到一個檔案,你可以使用這個模式,但它實際上只是為了我的健全性檢查,而且相當粗糙;)。

let runMultipleTasks() =
    // should give this as argument, as must be closed after all tasks completed
    let file = File.Open("output1.txt", FileMode.Create)
    let stream = new StreamWriter(file)

    // the actual creation of tasks 
    let tasks = createBunchOfTasks stream
    let combinedTask = join tasks

    // start the combined tasks
    combinedTask()

更簡單,更慣用的解決方案

在對任務串列、序列或陣列進行了更多修改之后,主要問題是它們必須被延遲。事實證明,您可以task使用for.

但是,您必須注意不要只使用yield,而是要let!與 結合使用yield這將確保任務將按順序等待:

let runMultipleTasks() = task {
    // should give this as argument, as must be closed after all tasks completed
    let file = File.Open("output1.txt", FileMode.Create)
    let stream = new StreamWriter(file)

    // the actual creation of tasks 
    let tasks = createBunchOfTasks stream |> Array.ofList
    let len = Array.length tasks
    let results = Array.zeroCreate len

    for i in 0..len - 1 do
        let! result = tasks[i]()  // ensure await-on-next
        results[i] <- result

    return List.ofArray results
}

注意:該庫IcedTasks有一種ColdTask型別,它允許以更簡單的方式進行上述操作,就好像它是一項正常任務一樣,并確保冷啟動。

uj5u.com熱心網友回復:

您可以做的一件事是使用惰性來防止任務過早開始。例如:

let createTask n =
    task {
        printfn $"Task {n} started"
        Thread.Sleep(2000)
        printfn $"Task {n} finished"
        return 100   n
    }

let lazyTasks =
    seq {
        for n = 1 to 10 do
            lazy createTask n
    }

所以在你的情況下,你會寫:

for cardTransactionWithOrder in cardTransactionswithOrder do
    let lazyMatchedTransaction = lazy matchTransaction(page,bnzBatch,cardTransactionWithOrder, xeroClient)
    yield lazyMatchedTransaction

然后,您可以像這樣按順序評估任何惰性任務序列:

let evalTasksSequential lazyTasks =
    task {
        return seq {
            for (lazyTask : Lazy<Task<_>>) in lazyTasks do
                yield lazyTask.Value.Result   // start task and wait for it to finish
        }
    }

測驗示例:

task {
    let! results = evalTasksSequential lazyTasks
    for result in results do
        printfn $"{result}"
} |> ignore

輸出:

Task 1 started
Task 1 finished
101
Task 2 started
Task 2 finished
102
Task 3 started
Task 3 finished
103
Task 4 started
Task 4 finished
104
Task 5 started
Task 5 finished
105
Task 6 started
Task 6 finished
106
Task 7 started
Task 7 finished
107
Task 8 started
Task 8 finished
108
Task 9 started
Task 9 finished
109
Task 10 started
Task 10 finished
110

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508499.html

標籤:异步 F# f#-异步

上一篇:嘗試在cog_loader上使用異步函式運行discord.py時出錯

下一篇:我的代碼說“無法讀取未定義的屬性”

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more