从actor到actor发送流(例如文件)

时间:2017-07-27 19:41:24

标签: c# akka.net akka.net-streams

我想将数据从一个actor中的流发送到另一个actor中的流。最后,这应该适用于远程演员。使用 Akka.NET Streams 这应该是一项简单的任务,但也许我误解了它。

这是 SenderActor

的一部分
var stream = new FileStream(FILENAME, FileMode.Open);
var materializer = Context.Materializer();
var source = StreamConverters.FromInputStream(() => stream, CHUNK_SIZE);
var result = source.To(Sink.ActorRef<ByteString>(this.receiver, new Messages.StreamComplete()))
    .Run(materializer);

注意:this.receiverIActorRef,其中应将数据发送到。{/ p>

ReceiverActor现在可以在流结束后收到所有ByteString条消息和Messages.StreamCompleted

如何在ReceiverActor中轻松组合?最好再次作为Stream

ReceiverActor 中,我尝试将所有ByteString条消息发送到应填充Source的{​​{1}}:

MemoryStream

class ReceiverActor : ReceiveActor { private readonly IActorRef streamReceiver; private readonly MemoryStream stream; public ReceiverActor() { this.stream = new MemoryStream(); this.streamReceiver = Source.ActorRef<ByteString>(128, Akka.Streams.OverflowStrategy.Fail) .To(StreamConverters.FromOutputStream(() => this.stream, true)) .Run(Context.Materializer()); Context.Watch(this.streamReceiver); Receive<ByteString>((message) => ReceivedStreamChunk(message)); Receive<Messages.StreamComplete>((message) => ReceivedStreamComplete(message)); Receive<Terminated>((message) => ReceivedTerminated(message)); ReceiveAny((message) => ReceivedAnyMessage(message)); } private void ReceivedTerminated(Terminated message) { Console.WriteLine($"[receiver] {message.ActorRef.Path.ToStringWithoutAddress()} terminated, local stream length {(this.stream.CanRead ? this.stream.Length : -1)}"); } private void ReceivedStreamComplete(Messages.StreamComplete message) { Console.WriteLine($"[receiver] got signaled that the stream completed, local stream length {this.stream.Length}"); } private void ReceivedStreamChunk(object message) { Console.WriteLine($"[receiver] got chunk, previous stream length {this.stream.Length}"); this.streamReceiver.Forward(message); } private void ReceivedAnyMessage(object message) { Console.WriteLine($"[receiver] got message {message.GetType().FullName}"); } } 填充为异步,当MemoryStream终止时,它会关闭流,因此我无法获取数据。

如何正确检索流?

更新我在本地工作:

感谢来自Akus.NET的gitter频道的Horusiath的输入,我能够直接收到streamReceiver,而不必在那里使用Akka.Stream。

ByteStrings

Receive<ByteString>((message) => ReceivedStreamChunk(message));

请注意,Akka.NET 1.3会将方法private void ReceivedStreamChunk(ByteString message) { var bytes = message.ToArray(); targetStream.Write(bytes, 0, bytes.Length); Console.WriteLine($"[receiver] got chunk, now stream length {this.stream.Length}"); } WriteTo(Stream)添加到WriteToAsync(Stream, CancellationToken)

仍然这对远程actor不起作用,因为接收actor系统会收到此错误(Serializer是Hyperion):

  

错误[没有为此对象定义无参数构造函数。]

实际上ByteString有一个无参数构造函数,但它是ByteString

我认为protected不可序列化?

1 个答案:

答案 0 :(得分:0)

通过在源和接收器之间插入转换流,将ByteString转换为byte[]时,我使用了远程actor。

示例:

FileIO.FromFile(...).Via(Flow.Create<ByteString>().Select(x => x.ToArray())).To(...)