Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous Akka.net F#有状态的参与者,等待多个FileSystemWatcher可观察事件_Asynchronous_F#_Filesystemwatcher_Observable_Akka.net - Fatal编程技术网

Asynchronous Akka.net F#有状态的参与者,等待多个FileSystemWatcher可观察事件

Asynchronous Akka.net F#有状态的参与者,等待多个FileSystemWatcher可观察事件,asynchronous,f#,filesystemwatcher,observable,akka.net,Asynchronous,F#,Filesystemwatcher,Observable,Akka.net,我对F#和Akka.Net都是新手,我试图通过他们实现以下目标: 我想创建一个actor(Tail),它接收一个文件位置,然后使用FileSystemWatcher和一些可观察对象侦听该位置的事件,并将它们作为消息转发给其他actor进行处理 我遇到的问题是,侦听事件的代码一次只拾取一个事件,而忽略所有其他事件。e、 g.如果我将20个文件复制到正在监视的目录中,它似乎只发送其中一个文件的事件 以下是我的演员代码: module Tail open Akka open Akka.FSharp

我对F#和Akka.Net都是新手,我试图通过他们实现以下目标:

我想创建一个actor(Tail),它接收一个文件位置,然后使用FileSystemWatcher和一些可观察对象侦听该位置的事件,并将它们作为消息转发给其他actor进行处理

我遇到的问题是,侦听事件的代码一次只拾取一个事件,而忽略所有其他事件。e、 g.如果我将20个文件复制到正在监视的目录中,它似乎只发送其中一个文件的事件

以下是我的演员代码:

module Tail

open Akka
open Akka.FSharp
open Akka.Actor
open System
open Model
open ObserveFiles
open ConsoleWriteActor

let handleTailMessages tm =
    match tm with
        | StartTail (f,r) ->
            observeFile f consoleWriteActor |!> consoleWriteActor

    |> ignore

let spawnTail =
    fun (a : Actor<IMessage> )  -> 
    let rec l (count : int) = actor{

        let! m = a.Receive()
        handleTailMessages m
        return! l (count + 1)
    } 
    l(0) 

要做到这一点,我花了不少功夫,任何关于如何更改它的建议,以便它在参与者运行时拾取并处理所有事件,都将不胜感激。

在设计这样的任务时,我们可以将其分为以下组件:

  • 创建负责接收所有消息的管理器—它的主要角色是响应传入的目录侦听请求。一旦请求进入,它将创建一个子角色,负责在此特定目录下进行侦听
  • 子参与者负责管理特定路径的
    FileSystemWatcher
    。它应该订阅传入事件,并将它们作为消息重定向给负责接收更改事件的参与者。它还应该在关闭时释放可支配资源
  • 负责接收变更事件的参与者-在我们的例子中,通过在控制台上显示它们
  • 示例代码:

    打开Akka.FSharp
    开放系统
    开放系统
    让system=system.create“observer system”Observable.map(fun x->x.Name+“”+x.ChangeType.ToString());
    fsw.Created |>Observable.map(funx->x.Name+“”+x.ChangeType.ToString());
    fsw.Deleted |>Observable.map(funx->x.Name+“”+x.ChangeType.ToString());
    fsw.rename |>Observable.map(fun x->x.Name+“”+x.ChangeType.ToString());]
    |>List.reduce Observable.merge
    
    |>Observable.subscribe(fun x->consoleWriter在设计这样的任务时,我们可以将其拆分为以下组件:

  • 创建负责接收所有消息的管理器-它的主要作用是响应传入的目录侦听请求。一旦请求传入,它将创建一个子角色,负责在此特定目录下侦听
  • 子参与者负责管理特定路径的
    FileSystemWatcher
    。它应该订阅传入事件,并将它们作为消息重定向到负责接收更改事件的参与者。它还应该在关闭时释放可支配资源
  • 负责接收变更事件的参与者-在我们的例子中,通过在控制台上显示它们
  • 示例代码:

    打开Akka.FSharp
    开放系统
    开放系统
    让system=system.create“observer system”Observable.map(fun x->x.Name+“”+x.ChangeType.ToString());
    fsw.Created |>Observable.map(funx->x.Name+“”+x.ChangeType.ToString());
    fsw.Deleted |>Observable.map(funx->x.Name+“”+x.ChangeType.ToString());
    fsw.rename |>Observable.map(fun x->x.Name+“”+x.ChangeType.ToString());]
    |>List.reduce Observable.merge
    
    |>Observable.subscribe(fun x->consoleWriter)我没有意识到你可以像创建observer那样创建一个演员,非常优雅。我没有意识到你可以像创建observer那样创建一个演员,非常优雅。
    module ObserveFiles
    open System
    open System.IO
    open System.Threading
    open Model
    open Utils
    open Akka
    open Akka.FSharp
    open Akka.Actor
    
    
    
    let rec observeFile (absolutePath : string) (a : IActorRef )  = async{
    
        let fsw = new FileSystemWatcher(
                            Path = Path.GetDirectoryName(absolutePath), 
                            Filter = "*.*",
                            EnableRaisingEvents = true, 
                            NotifyFilter = (NotifyFilters.FileName ||| NotifyFilters.LastWrite ||| NotifyFilters.LastAccess ||| NotifyFilters.CreationTime ||| NotifyFilters.DirectoryName)
                            )
    
        let prepareMessage  (args: EventArgs) =
            let text = 
                match box args with
                | :? FileSystemEventArgs as fsa ->
                    match fsa.ChangeType with
                    | WatcherChangeTypes.Changed -> "Changed " + fsa.Name
                    | WatcherChangeTypes.Created ->  "Created " + fsa.Name
                    | WatcherChangeTypes.Deleted -> "Deleted " + fsa.Name
                    | WatcherChangeTypes.Renamed -> "Renamed " + fsa.Name
                    | _ -> "Some other change " + fsa.ChangeType.ToString()
                | :? ErrorEventArgs as ea -> "Error: " + ea.GetException().Message
                | o -> "some other unexpected event occurd" + o.GetType().ToString()
            WriteMessage text 
    
    
        let sendMessage x = async{  async.Return(prepareMessage x) |!> a
                                    return! observeFile absolutePath a }
    
        let! occurance  = 
            [
            fsw.Changed |> Observable.map(fun x -> sendMessage (x :> EventArgs));
            fsw.Created |> Observable.map(fun x -> sendMessage (x :> EventArgs));
            fsw.Deleted |> Observable.map(fun x -> sendMessage (x :> EventArgs));
            fsw.Renamed |> Observable.map(fun x -> sendMessage (x :> EventArgs));
            fsw.Error |> Observable.map(fun x -> sendMessage (x :> EventArgs));
            ] 
            |> List.reduce Observable.merge
            |> Async.AwaitObservable
    
        return! occurance
    }