2016-09-22 80 views
3

嗨,我尝试了F#WMI类提供商的代码示例获取计数器值看起来像这样如何连续F#WMI类提供商

type Local = WmiProvider<"localhost"> 
let data = Local.GetDataContext() 
let memory = [for d in data.Win32_PerfFormattedData_PerfOS_Memory -> d.AvailableBytes] 

内存在这种情况下是System.Nullable名单。所以问题是如何获得这个列表的连续更新?目前我的代码看起来像这样

let printMemory() = 
    let rec outerLoop = 
     let memory = [for d in data.Win32_PerfFormattedData_PerfOS_Memory -> d.AvailableBytes] 
     let rec loop (values:Nullable<uint64> list) = 
      Thread.Sleep(1000) 
      match values with 
      |[] -> printfn "empty" 
        outerLoop 
      |h::t -> printfn "value = %d" h.Value 
        loop t 
     loop memory 
    outerLoop 

所以,我必须请求新的列表(记忆)每一次,这是正确的做法? 例如System.Diagnostics的PerformanceCounter计数器实现NextValue,是否有类似WMI类型提供程序的东西?谢谢!

回答

1

如果您不希望阻止当前线程,Rx提供用于处理一个很好的API:

// nuget FSharp.Management 
#I "packages/FSharp.Management/lib/net40" 
// nuget System.Reactive 
#I "packages/System.Reactive.Core/lib/net46" 
#I "packages/System.Reactive.Linq/lib/net46" 
#I "packages/System.Reactive.Interfaces/lib/net45" 

#r "System.Management.dll" 
#r "FSharp.Management.WMI.dll" 
#r "System.Reactive.Core.dll" 
#r "System.Reactive.Interfaces.dll" 
#r "System.Reactive.Linq.dll" 

open FSharp.Management 
open System 
open System.Reactive.Linq 
open System.Runtime.InteropServices 
open System.Text 

[<DllImport("shlwapi.dll", CharSet = CharSet.Unicode)>] 
extern int64 StrFormatKBSize(int64 qdw, [<MarshalAs(UnmanagedType.LPTStr)>] StringBuilder pszBuf, int cchBuf); 

let bytesToString byteCount = 
    let sb = StringBuilder(32); 
    StrFormatKBSize(byteCount, sb, sb.Capacity) |> ignore 
    sb.ToString() 

type Local = WmiProvider<"localhost"> 
let memory = Local.GetDataContext().Win32_PerfFormattedData_PerfOS_Memory 
let freeMem() = 
    // I don't know the semantics of Win32_PerfFormattedData_PerfOS_Memory 
    // you might want to adjust the following 
    memory 
    |> Seq.choose (fun d -> d.AvailableBytes |> Option.ofNullable) 
    |> Seq.exactlyOne 

let print m = 
    printfn "At %A: free %s" DateTime.UtcNow (bytesToString(int64 m)) 

// Immediately start to produce values every 1 second (on thread pool) 
Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds 1.0) 
|> Observable.map(fun _ -> freeMem()) 
// only propagate a value if it differs from the previous one 
|> Observable.DistinctUntilChanged 
|> Observable.subscribe print 

// Causes a non-fatal error in VS Interactive, works in FSI 
Console.ReadKey() |> ignore 

该脚本产生例如

在2016年9月27日10点24分10秒:免费8'053'600 KB
在2016年9月27日10:24:11:免费8'053'604 KB
在2016年9月27日10: 24:13:免费8'053'600 KB
At at 27.09.2016 10:24:14:free 8'053'604 KB
At 27.09.2016 10:24:15:free 8'054'472 KB
At 27.09.2016 10:24:16:free 8'054'468 KB
At at 27.09.2016 10:24:17:free 8'054'496 KB
At 27.09.2016 10:24:18:free 8'054'480 KB
At 27.09.2016 10:24:20:free 8'054'492 KB

0

你将不得不作出的调用明确新的值,或使用刷新对象WmiSmoObject.Refresh

F# 
abstract Refresh : unit -> unit 
override Refresh : unit -> unit 
+1

WmiSmoObject是Microsoft.SqlServer.Management的一部分,我不想监视它。我已经明确要求更新每个扫描周期,只是想知道是否可以更新 –