2017-01-03 8 views
5

I持ってファイルをダウンロードし、コンソールに私に語った、このコードファイルどのように大きいです:F#:最初のイベントに対して1つのアクションを1回だけ実行します。

use webClient = new WebClient() 

let lockObj = new Object() 
let mutable firstProgressEvent = true 
let onProgress (progressEventArgs: DownloadProgressChangedEventArgs) = 
    lock lockObj (fun _-> 
     if (firstProgressEvent) then 
      let totalSizeInMB = progressEventArgs.TotalBytesToReceive/1000000L 
      Console.WriteLine ("Starting download of {0}MB...", totalSizeInMB) 
     firstProgressEvent <- false 
    ) 

webClient.DownloadProgressChanged.Subscribe onProgress |> ignore 
let task = webClient.DownloadFileTaskAsync (uri, Path.GetFileName(uri.LocalPath)) 
task.Wait() 

同じことをする方法はありますが、どちらもロックも可変VARSを使用していますか?ここで

+1

私はあなたがここに –

+0

正確にどのようにジョンを怠惰なタイプを使用したいかもしれないと思いますか? – knocte

+0

イベントを処理するたびに '.Force()'を呼び出すが、最初の値をベイク処理する必要があるため、動作しないので、怠け者ではできないと思います。 [memoizeパターン](https://blogs.msdn.microsoft.com/dsyme/2007/05/31/a-sample-of-the-memoization-pattern-in-f/)を使って見ることができます。値が変わるたびに(決して)印刷されます。しかし、これはすでに悪いことではないにしても、あなたと同じくらい冗長になります。 – Stuart

答えて

5

は、反応性の拡張機能を使用して一つの方法である:

open System.Net 
open FSharp.Control 

let webClient = new WebClient() 
let disposable = 
    Observable.take 1 webClient.DownloadProgressChanged 
    |> Observable.subscribe (fun progress -> printfn "%A" (progress.TotalBytesToReceive)) 
+2

'FSharp.Control'名前空間の[Observable](https://msdn.microsoft.com/visualfsharpdocs/conceptual/control.observable-module-%5bfsharp%5d)はF#に組み込まれており、' take'関数はありません。ですから、このNuGetパッケージが動作するには、[FSharp.Control.Reactive](https://www.nuget.org/packages/FSharp.Control.Reactive)が必要です。 – TheQuickBrownFox

+0

ありがとう@TheQuickBrownFox、私は – knocte

関連する問題