Reentrant 示例演示了对服务实现使用 ConcurrencyMode.Reentrant 的必要性和含义。 ConcurrencyMode.Reentrant 表示服务(或回调)在给定时间只处理一条消息(类似于 ConcurencyMode.Single
)。 为了确保线程安全,Windows Communication Foundation (WCF) 锁定 InstanceContext
处理消息,以便无法处理其他消息。 在处于可重入模式的情况下,InstanceContext
将仅在服务进行传出调用之前解除锁定,从而允许后续调用(可按示例中的演示重入),并在下次进入服务时被锁定。 为了演示此行为,示例演示了客户端和服务如何使用双工协定相互发送消息。
定义的合同是一个双向合同,其中Ping
方法由服务实现,回调方法Pong
由客户端实现。 客户端用滴答计数调用服务的 Ping
方法,从而启动调用。 服务检查时钟周期计数是否不等于 0,然后在递减时钟周期计数时调用回调 Pong
方法。 这由示例中的以下代码完成。
public void Ping(int ticks)
{
Console.WriteLine("Ping: Ticks = " + ticks);
//Keep pinging back and forth till Ticks reaches 0.
if (ticks != 0)
{
OperationContext.Current.GetCallbackChannel<IPingPongCallback>().Pong((ticks - 1));
}
}
回调的 Pong
实现具有与 Ping
实现相同的逻辑。 也就是说,它会检查时钟周期计数是否不为零,然后在回调通道上调用 Ping
该方法(在本例中,它是用于发送原始 Ping
消息的通道),时钟周期计数递减 1。 当滴答计数达到 0 时,该方法返回,从而将所有回复解包回启动该调用的客户端进行的第一个调用。 回调实现中显示了此过程。
public void Pong(int ticks)
{
Console.WriteLine("Pong: Ticks = " + ticks);
if (ticks != 0)
{
//Retrieve the Callback Channel (in this case the Channel which was used to send the
//original message) and make an outgoing call until ticks reaches 0.
IPingPong channel = OperationContext.Current.GetCallbackChannel<IPingPong>();
channel.Ping((ticks - 1));
}
}
Ping
和Pong
两种方法都是请求/答复,这意味着第一次调用Ping
会等待,直到调用CallbackChannel<T>.Pong()
返回后才有返回结果。 在客户端上,在由 Pong
方法进行的下一个 Ping
调用返回前,该方法不会返回。 由于回调和服务在答复挂起请求之前,必须进行传出请求/答复调用,因此这两个实现必须使用 ConcurrencyMode.Reentrant 行为进行标记。
设置、生成和运行示例
确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。
若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。
若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。
演示
若要运行示例,请生成客户端和服务器项目。 然后打开两个命令窗口,并将目录更改为 <sample>\CS\Service\bin\debug 和 <sample>\CS\Client\bin\debug 目录。 然后键入 service.exe
以启动服务,再使用作为输入参数传递的初始滴答值调用 Client.exe。 显示了 10 次滴答的示例输出。
Prompt>Service.exe
ServiceHost Started. Press Enter to terminate service.
Ping: Ticks = 10
Ping: Ticks = 8
Ping: Ticks = 6
Ping: Ticks = 4
Ping: Ticks = 2
Ping: Ticks = 0
Prompt>Client.exe 10
Pong: Ticks = 9
Pong: Ticks = 7
Pong: Ticks = 5
Pong: Ticks = 3
Pong: Ticks = 1