Хороший вопрос. Прежде чем клиентское приложение вызывает метод, оно открывает канал. Канал используется для передачи всех данных. Существует два способа отправки: 1) надежный сеанс - когда ваши пакеты надежно удалены, а взломанные пакеты повторно отправлены, 2) упорядочение - когда запросы на службу вычисляются в порядке их передачи от клиента (а не как они доставляются) , Если у вас есть надежный заказанный сеанс, и у хоста службы возникают проблемы с данными после закрытия приложения, хост попытается запросить у клиента данные повторно, а после отсутствия ответа отклонит все ваши запросы. В другой ситуации (ненадежной) после открытия канала вы можете отправлять данные и уничтожать связь, односторонний метод вычислит ваш запрос, если не будет исключения.
Чтобы проверить некоторые возможности, связанные с проблемой обслуживания (однако не совсем так, ваша проблема с клиентом полезна), я создаю решение:
1) Библиотека проекта "WcfContracts" с одним файлом "IService1.cs":
[ServiceContract]
public interface IService1
{
[OperationContract]
void ThrowException();
[OperationContract(IsOneWay=true)]
void ThrowExceptionUseIsOneWay();
}
2) Консольный проект "WcfConsoleHoster", который имеет ссылку на два "WcfContracts" и состоит из трех файлов:
a) Service1.cs, который является реализацией службы
public class Service1 : WcfContracts.IService1
{
public void ThrowException()
{
throw new Exception("Basic exception");
}
public void ThrowExceptionUseIsOneWay()
{
throw new Exception("Basic exception using IsOneWay=true");
}
}
b) Program.cs, который имеет точку входа по умолчанию и просто запускает службу
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();
Console.WriteLine("host 1 opened");
Console.ReadKey();
}
в) Сервис "App.config"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="behavourHttpGet" name="WcfConsoleHoster.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WcfConsoleHoster/Service1/" />
</baseAddresses>
</host>
<endpoint binding="wsHttpBinding" contract="WcfContracts.IService1" />
<endpoint address ="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="behavourHttpGet">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
3) Консольный проект "WcfConsoleClient", который просто вызывает сервис
а) В "Program.cs"
Console.WriteLine("Wcf client. Press any key to start");
Console.ReadKey();
ChannelFactory<IService1> factory = new ChannelFactory<IService1>("Service1_Endpoint");
IService1 channel = factory.CreateChannel();
//Call service method
channel.ThrowException();
Console.WriteLine("Operation executed");
Console.ReadKey();
б) Клиент "App.config"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="Service1_Endpoint"
address="http://localhost:8732/Design_Time_Addresses/WcfConsoleHoster/Service1/"
binding="wsHttpBinding"
contract="WcfContracts.IService1">
</endpoint>
</client>
</system.serviceModel>
</configuration>
1. Вызов исключения. Сначала мы вызываем двусторонний метод , который выдает исключение на хосте сервера. Затем это исключение возвращается к клиенту и канал поднимает его на стороне клиента, приложение уничтожается. Конечно, вы можете справиться с этим с помощью блока try () catch {}.
Давайте посмотрим так же с односторонним методом , вызвав channel.ThrowExceptionUseIsOneWay();
. Исключение возникает в хосте службы, но на стороне клиента нет исключения, и мы получаем «Операция выполнена». Важно понимать, что канал будет недоступен для следующего использования.
Так что IsOneWay=true
работает как положено - отправляет сообщение только одним способом. Вы не можете вернуть какой-либо объект из метода (ожидается void) и не можете использовать FaultContract или получить InvalidOperationException после запуска службы.
2. Thread.Sleep (). Следующий тест для массовой операции с Thread.Sleep()
.
IService1
расширен до
[OperationContract]
int ThreadSleep();
[OperationContract(IsOneWay=true)]
и реализация в Service1.cs в ожидании 5 секунд
public int ThreadSleep()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
return 1;
}
public void ThreadSleepUseIsOneWay()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
}
Теперь небольшая модификация для клиента для подсчета истекшего времени вызова
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
//call methode
channel.ThreadSleep();
stopwatch.Stop();
Console.WriteLine(string.Format("Operation executed in {0} seconds", stopwatch.Elapsed.Seconds));
Console.ReadKey();
Вызов двустороннего метода ThreadSleep()
приводит к результату «Операция выполнена за 7 секунд» (5 секунд для ожидания потока + 2 секунды для инициализации канала).
One way method
с вызовом channel.ThreadSleepUseIsOneWay()
имеет результат "0 секунд"! Там нет ожидания ответа службы!
Лучше всего использовать NetNamedPipeBinding , который является надежным и быстрым соединением на одном компьютере.