我想将数据从一个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.receiver
是IActorRef
,其中应将数据发送到。{/ 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
不可序列化?
答案 0 :(得分:0)
通过在源和接收器之间插入转换流,将ByteString
转换为byte[]
时,我使用了远程actor。
示例:
FileIO.FromFile(...).Via(Flow.Create<ByteString>().Select(x => x.ToArray())).To(...)