Повторный вход ConcurrencyMode
Этот образец демонстрирует необходимость и последствия использования ConcurrencyMode.Reentrant в реализации службы. Поведение ConcurrencyMode.Reentrant подразумевает, что служба (или обратный вызов) обрабатывает только одно сообщение в данный момент времени (аналогично ConcurencyMode.Single). Для обеспечения потокобезопасности Windows Communication Foundation (WCF) блокирует объект InstanceContext, обрабатывающий сообщение, что делает невозможной обработку других сообщений. В режиме Reentrant объект InstanceContext разблокируется непосредственно перед тем, как служба делает исходящий вызов, что делает возможным последующий вызов (который может быть реентерабельным, как показано в этом образце), и снова блокируется при следующем его поступлении в службу. Для демонстрации этого поведения в образце показано, как клиент и служба могут отправлять сообщения друг другу, используя дуплексный контракт.
Определенный в примере контракт является дуплексным: метод Ping
реализуется службой, а метод обратного вызова Pong
реализуется клиентом. Клиент вызывает метод Ping
сервера со счетчиком тактов, тем самым инициируя вызов. Служба проверяет, отличен ли счетчик тактов от нуля, и затем вызывает метод обратного вызова 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.
Чтобы выполнить построение версии решения для языка C# или Visual Basic .NET, следуйте инструкциям раздела Построение образцов Windows Communication Foundation.
Чтобы выполнить образец на одном или нескольких компьютерах, следуйте инструкциям раздела Running the Windows Communication Foundation Samples.
Демонстрации
Чтобы выполнить образец, постройте клиентский и серверный проекты. Затем откройте два окна командной строки и перейдите в каталоги <образец>\CS\Service\bin\debug и <образец>\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
![]() |
---|
Образцы уже могут быть установлены на компьютере. Перед продолжением проверьте следующий каталог (по умолчанию).
<диск_установки>:\WF_WCF_Samples
Если этот каталог не существует, перейдите на страницу Образцы Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) для .NET Framework 4, чтобы загрузить все образцы Windows Communication Foundation (WCF) и WF. Этот образец расположен в следующем каталоге.
<диск_установки>:\WF_WCF_Samples\WCF\Basic\Services\Reentrant
|