如何使用F#WMI类型提供程序连续获取计数器值

时间:2016-09-22 22:06:38

标签: f# type-providers

您好我正在尝试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类型提供程序是否有类似的东西?谢谢!

2 个答案:

答案 0 :(得分: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&#39; 053&#39; 600 KB
  在2016年9月27日10:24:11:免费8&#39; 053&#; 604 KB
  在2016年9月27日10:24:13:免费8&#39; 053&#39; 600 KB
  在2016年9月27日10:24:14:免费8&#39; 053&#; 604 KB
  在2016年9月27日10:24:15:免费8&#39; 054&#39; 472▼   在2016年9月27日10:24:16:免费8&#39; 054&#39; 468 KB
  2016年9月27日10:24:17:免费8&#39; 054&#39; 49   在2016年9月27日10:24:18:免费8&#39; 054&#39; 480 KB
  在2016年9月27日10:24:20:免费8&#39; 054&#39; 492

答案 1 :(得分:0)

您必须显式调用新值或使用刷新对象WmiSmoObject.Refresh

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