2012-01-12 6 views
2

У нас есть приложение, которое отправляет объект, в данном случае «printJob», в Службу. В зависимости от количества транзакций, которые у нас есть, этот процесс может занять некоторое время. Как только Служба выполняет то, что она делает, он возвращает приложение PrintJobID к приложению.WCF Time Out Issue

PrintGatewayClient printClient = new PrintGatewayClient(); 
PrintService.ServiceJob printJob = new PrintService.ServiceJob(); 
printJob.ServicePrintItems = checkList.ToArray(); 

try 
{ 
    currentBatch.PrintJobID = printClient.SubmitPrintJob(printJob); 
    PaymentBatchesGateway.Update(currentBatch); 
} 
catch (System.Exception ex) 
{ 
    throw ex; 
} 

printClient.Close(); 

В appliation ждет и ждет printClient, чтобы закончить его работу и получить целое число от «PrintJobID», а затем обновляет таблицу с этим идентификатором. Однако, когда крупные партии побежал, мы получим следующее сообщение об ошибке:

The request channel timed out while waiting for a reply after 00:04:59.9062464. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. 

Я смотрел на наш файл web.config на NetTcpBinding:

<netTcpBinding> 
    <binding name="NetTcpBinding_IPrintGateway" closeTimeout="00:01:00" 
     openTimeout="00:01:00" receiveTimeout="02:00:00" sendTimeout="02:00:00" 
     transactionFlow="false" transferMode="Buffered" 
     transactionProtocol="OleTransactions" 
     hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
     maxBufferPoolSize="524288" maxBufferSize="50000000" maxConnections="10" 
     maxReceivedMessageSize="50000000"> 

    <readerQuotas maxDepth="5000" maxStringContentLength="150000" 
     maxArrayLength="16384" maxBytesPerRead="50000000" 
     maxNameTableCharCount="16384" /> 

    <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> 
    <security mode="None"> 
      <transport clientCredentialType="None" protectionLevel="None" /> 
      <message clientCredentialType="None" /> 
    </security> 
    </binding> 
<netTcpBinding> 

<client> 
    <endpoint address="http://server/printgateway/PrintGateway.svc" 
     binding="basicHttpBinding" 
     bindingConfiguration="BasicHttpBinding_IPrintGateway" 
     contract="PrintService.IPrintGateway" 
     name="BasicHttpBinding_IPrintGateway" />  
</client> 

Я не мог найти время из 00 : 05: 00 в любом месте в коде. Может кто-нибудь объяснить и рассказать мне, как продлить этот тайм-аут. Могу ли я сделать это в коде, в web.config, на сервере?

Спасибо!

+0

Я не особо осведомлен о WCF, и я не знаю, откуда этот 5-минутный тайм-аут. Однако для тестирования вы пытались увеличить значения closeTimeout, openTimeout, receiveTimeout и sendTimeout в своем на что-то намного выше и увидеть, все ли происходит искупление? Я также считаю, что вы можете создать соответствующий объект привязки, установить привязку .SendTimeout = TimeSpan.FromMinutes (60); (а также другие значения таймаута) в коде и использовать этот объект при создании своего Сервисного клиента. – Dan

ответ

1

Наличие блока потока на служебном вызове, ожидающем ответа еще на 60 секунд, является чрезмерным и представляет собой плохой выбор дизайна. Вы, конечно, не хотите увеличивать это до 5 минут, а если 5 минут, то почему не час? Это не реалистичное или поддерживающее решение.

Вместо этого вам будет гораздо лучше использовать асинхронные вызовы.

Когда вы добавляете ссылку на службу в проект, в диалоговом окне «Добавить ссылку на службу» нажмите «Дополнительно» и в разделе «Клиент» выберите «Генерировать асинхронные операции». Прокси-классы, созданные из этого, будут иметь [OperationName] Completed events и [OperationName] методы Async для каждого OperationName в контракте на обслуживание.

var client = new Service1Client(); 
    client.GetDataCompleted += Client_GetDataCompleted; // specify the callback method 
    client.GetDataAsync(0); 
    // ... 


static void Client_GetDataCompleted(object sender, GetDataCompletedEventArgs e) 
{ 
    var response = e.Result; 
    // ... 
} 

Метод обратного вызова запланирован в потоке после того, как ответное сообщение было получено инфраструктурой WCF. Подробнее в разделе «Как: асинхронно вызывать операции службы WCF» http://msdn.microsoft.com/en-us/library/ms730059.aspx.

+0

К сожалению, я унаследовал приложение от другого разработчика, который покинул компанию. Я просто поддерживаю приложение. Можете ли вы объяснить, что вы подразумеваете под «асинхронными вызовами службы»? – Turp

+0

Wcf не блокируется, потому что один экземпляр обслуживает клиента за чрезмерное количество времени. Поведение по умолчанию - это создать другой экземпляр для подачи нового запроса. Но если говорить, что службы async могут быть хорошей идеей, это просто не решит проблему с тайм-аутом, так как сервер все еще должен выполнять свою работу, поэтому, вероятно, лучше решить проблему производительности. Повышение таймаута также будет нормально, если сервер будет обрабатывать большие передачи данных или аналогичные задачи, которые, как ожидается, будут длительными. – faester

+0

@faester, вы правы, что экземпляр за звонок является стандартной моделью instanced в WCF для служб. Код, показанный здесь, представляет собой код клиента. Это клиент блокирует, а не службу. Некоторые операции обслуживания, такие как операции бизнес-процесса, могут потребовать очень много времени (часы, недели) для завершения и возврата ответного сообщения. Клиент выбирает вызов службы синхронно (блоки потоков, ожидающие ответа) или асинхронно (поток не блокирует ожидание ответа). –

1

Существует два файла конфигурации: один на стороне обслуживания и один на стороне потребителя. Похоже, у вас есть потребительская конфигурация. Вероятно, вы найдете 5-минутный тайм-аут, установленный в сервисе conifg.

Однако я согласен с Visual Stuart, что долго ждать синхронных вызовов услуг нежелательно. Что должно произойти, так это то, что задания печати добавляются в очередь, и после их обработки ответ может быть отправлен вызывающему пользователю.

Однако это будет означать значительное усилие перепланировки.

1

У нас была аналогичная ситуация для элемента управления Silverlight, инициирующего бизнес-логику, которая в зависимости от того, какие операции были выбраны, приведет к таймауту. Я применил сценарий опроса, такой как ниже

  1. Метод службы WCF, вызванный с помощью StartOperation, который возвратил пользователю уникальный идентификатор.
  2. Метод обслуживания запускает фоновый процесс, который выполняет работу и просто сообщает о статусе.
  3. Потребитель вызывает отдельный режим обслуживания wcf с уникальным идентификатором, чтобы получить статус.
  4. Метод статуса проверяет фоновый процесс (я использовал одноэлементный менеджер, который имел запущенные процессы в словаре поиска) и возвращает его статус.
  5. Потребительские звонки №3 до тех пор, пока не будет сообщено о завершении.
  6. Одиночный менеджер может очистить процесс после того, как он сделал отчеты и/или разрешить потребителю сообщать об этом и очистить его.