据我了解,TPL 数据流为 .NET 程序员提供了 Actor 编程模型(不涉及以前可用的 3rd 方解决方案)。Actor 模型本身声明每个 Actor 可以支持三种基本操作:“发送”、“创建”和“成为”。在 TPL Dataflow 中处理“成为”语义的“正确”方法是什么?
请考虑以下示例:
static void TestBecome()
{
TransformBlock<string, string> dispatcher = null;
dispatcher = new TransformBlock<string, string>
(
val =>
{
Console.WriteLine("Received for processing {0}", val);
switch (val)
{
case "CREATE": // create linked node
{
dispatcher.LinkTo(CreateNewNode().Item2);
break;
}
case "BECOME": // transform the node ('become' semantics)
{
var newNode = CreateNewNode();
Console.WriteLine("Dispatcher transformed to {0}", newNode.Item1);
dispatcher = newNode.Item2;
break;
}
default: return val; // dispatch the value to linked node (one of)
}
return string.Empty; // 'empty unit'
}
);
dispatcher.SendAsync("CREATE").ContinueWith(res => Console.WriteLine("Send CREATE: {0}", res.Result));
dispatcher.SendAsync("CREATE").ContinueWith(res => Console.WriteLine("Send CREATE: {0}", res.Result));
dispatcher.SendAsync("msg1").ContinueWith(res => Console.WriteLine("Send msg1: {0}", res.Result));
dispatcher.SendAsync("msg2").ContinueWith(res => Console.WriteLine("Send msg2: {0}", res.Result)); ;
Thread.Sleep(1000);
dispatcher.SendAsync("BECOME").ContinueWith(res => Console.WriteLine("Send BECOME: {0}", res.Result)); ;
Thread.Sleep(1000);
dispatcher.SendAsync("msg3").ContinueWith(res => Console.WriteLine("Send msg3: {0}", res.Result));
dispatcher.SendAsync("msg4").ContinueWith(res => Console.WriteLine("Send msg4: {0}", res.Result));
dispatcher.SendAsync("msg5").ContinueWith(res => Console.WriteLine("Send msg5: {0}", res.Result));
}
static Tuple<string, TransformBlock<string, string>> CreateNewNode()
{
var id = Guid.NewGuid().ToString("N");
var node = new TransformBlock<string, string>
(
val =>
{
if (string.IsNullOrWhiteSpace(val)) // pass trough 'empty unit'
return val;
Console.WriteLine("NODE {0}: {1}", id, val);
return val;
}
, new ExecutionDataflowBlockOptions { BoundedCapacity = 3 }
);
return Tuple.Create(id, node);
}
我发现这种“变得”笨拙的方式:我没有改变演员的行为,而是改变了演员实例本身(这会导致不希望的效果)。什么是“正确”的方式?
还有一个问题:据我所知,标准的 TDF 块要么永远不会将消息传递给链接的笔记(例如 ActionBlock,如果这样的逻辑不是手工编写的),要么总是这样做(大多数块)。我是否正确,仅在某些情况下(并非总是)发送消息的逻辑应作为自定义块实现?