2017-03-23 10 views
1

作業中のC#サンプルをOOP version of F#に移植しようとしました。F#を使用してProps.Createを実装する方法

リモートアクター(別のプロセス上)はメッセージを受信して​​いません。

私は、次のエラーが表示されます

[ERROR][3/23/2017 4:39:10 PM][Thread 0008][[akka://system2/system/endpointManage 
r/reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem1%40localhost%3A8090-1/endpointW 
riter#1919547364]] AssociationError [akka.tcp://[email protected]:8080] <- akka. 
tcp://[email protected]:8090: Error [Object reference not set to an instance of 
an object.] [ at Akka.Serialization.Serialization.FindSerializerForType(Type o 
bjectType) 
    at Akka.Remote.Serialization.DaemonMsgCreateSerializer.GetArgs(DaemonMsgCreat 
eData proto) 
    at Akka.Remote.Serialization.DaemonMsgCreateSerializer.FromBinary(Byte[] byte 
s, Type type) 
    at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serialize 
rId, String manifest) 

ここで働いてC#バージョンです:

using (var system = ActorSystem.Create("system1", config)) 
{ 
    var reply = system.ActorOf<ReplyActor>("reply"); 

    //create a remote deployed actor 
    var remote1 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor1"); 
    var remote2 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor2"); 
    var remote3 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor3"); 

    var hashGroup = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config))); 

    Task.Delay(500).Wait(); 

    var routee1 = Routee.FromActorRef(remote1); 
    hashGroup.Tell(new AddRoutee(routee1)); 

    var routee2 = Routee.FromActorRef(remote2); 
    hashGroup.Tell(new AddRoutee(routee2)); 

    var routee3 = Routee.FromActorRef(remote3); 
    hashGroup.Tell(new AddRoutee(routee3)); 

    Task.Delay(500).Wait(); 

    for (var i = 0; i < 5; i++) 
    { 
     for (var j = 0; j < 7; j++) 
     { 
      var message = new SomeMessage(j, $"remote message: {j}"); 
      hashGroup.Tell(message, reply); 
     } 
    } 

    Console.ReadLine(); 
} 

はここでOOPを使用してF#にポートです:

use system = ActorSystem.Create("system1", config) 
let reply = system.ActorOf<ReplyActor>("reply") 

let props1 = Props.Create(fun() -> SomeActor() :> obj) 
let props2 = Props.Create(fun() -> SomeActor() :> obj) 
let props3 = Props.Create(fun() -> SomeActor() :> obj) 

let remote1 = system.ActorOf(props1.WithRouter(FromConfig.Instance), "remoteactor1") 
let remote2 = system.ActorOf(props2.WithRouter(FromConfig.Instance), "remoteactor2") 
let remote3 = system.ActorOf(props3.WithRouter(FromConfig.Instance), "remoteactor3") 

let hashGroup = system.ActorOf(Props.Empty.WithRouter(ConsistentHashingGroup(config))) 
Task.Delay(500).Wait(); 

let routee1 = Routee.FromActorRef(remote1); 
hashGroup.Tell(new AddRoutee(routee1)); 

let routee2 = Routee.FromActorRef(remote2); 
hashGroup.Tell(new AddRoutee(routee2)); 

let routee3 = Routee.FromActorRef(remote3); 
hashGroup.Tell(new AddRoutee(routee3)); 

Task.Delay(500).Wait(); 

for i = 0 to 5 do 
    for j = 0 to 7 do 

     let message = new HashMessage(j, sprintf "remote message: %i" j); 
     hashGroup.Tell(message, reply); 

Console.ReadLine() |> ignore 

質問:Props.Createメソッドを呼び出すときに、私はSomeActorオブジェクト型にアップキャストすると仮定

アム?

let props1 = Props.Create(fun() -> SomeActor() :> obj) 
let props2 = Props.Create(fun() -> SomeActor() :> obj) 
let props3 = Props.Create(fun() -> SomeActor() :> obj) 

上記のコードは私が知っている唯一の違いです。

唯一の違いは、tcpパスです。

C#のTCP:

remote { 
    dot-netty.tcp { 
     port = 8090 
     hostname = localhost 
    } 

F# 'sのTCP:

remote { 
     helios.tcp { 
      port = 8090 
      hostname = localhost 
     } 
+2

重要な違いかどうかわかりませんが、F#ではforループが1要素大きくなります(C#では '<='ではなく<''をチェックするので)。 – kvb

+0

その観測kvbありがとうございました。 –

+0

'obj'にアップキャストしないとどうなりますか? 'Create'のオーバーライドがたくさんあるように見えるので、アップキャストが別のものを使用するように強制していて、結果を説明できるのであれば、私は驚かないでしょう。 – kvb

答えて

3

小道具オブジェクトは、ターゲット・俳優の作成プロセスの記述子です。さらに、ネットワーク経由で渡されるメッセージに含まれることもあるため、シリアライズ可能でなければなりません。

このように動作するために、Propsは内部的に(actor-type、actor-constructor-argumentsの形式で)アクター構成を記述します。 Props.Create(() => new Actor())はここではヘルパーに過ぎません。実際には、コンストラクタの式を引数付きの型情報に分解します。これがnew Actor()式でのみ動作する理由です。

F#コードの問題は、アクターの作成をF#関数として定義していることです。これは、deconstructorが処理方法を知らないためです。

Props.Create(typeof<Actor>, [| arg1; arg2 |]) 

しかし、あなたは自分でコンストラクタパラメータの正確さを保つ必要があります。また、アークリングをtyped version of propsと組み合わせて使用​​することもできます。

関連する問題