2010-03-16 3 views
4

Мне нужно приложение консоли, которое вызовет веб-метод.Async webmethod без таймаута

Он должен быть асинхронными и без тайм-аута (мы не знаем, сколько времени займет этот метод, чтобы справиться с задачей

Является ли это хороший способ:.

[WebMethod] 
[SoapDocumentMethod(OneWay = true)] 

??

+1

Вам нужен ответ с вашего веб-метода? – lajuette

+5

Использование веб-служб ASMX не является «хорошим способом», если вы не застряли с использованием .NET 2.0. Microsoft теперь рассматривает веб-службы ASMX как «устаревшую технологию». Все новые разработки веб-сервисов должны быть выполнены с использованием WCF. –

+2

Статья в MSDN с меткой примечания о том, что ASMX является «устаревшим» (в то время как более новые статьи в MSDN об ASMX do * not * несут эту заметку) не делает ASMX еще хуже, чем он делает. В лучшем случае вся эта дискуссия ортогональна вопросу Фенево. –

ответ

5

Не используйте односторонний, если вам нужны результаты

Во-первых, если вам нужен ответ от вашего метода, вы не хотите, чтобы [SoapDocumentMethod(OneWay = true)]. Этот атрибут создает вызов «огонь и забвение», который никогда не возвращает ответ обратно на катер и должен возвращать void. Вместо этого используйте обычный вызов метода и назовите его async.

Один или два метода?

Если вы используете ASMX, существует два основных решения: один метод с очень длинным таймаутом или два метода (как @Aaronaught suggested above): один для запуска операции и возврата идентификатора операции, а другой - передать идентификатор и получить результаты (если они доступны).

Лично я бы не рекомендовал это два-метода подход в большинстве случаев из-за дополнительной сложности участие, в том числе:

  • клиента и код сервера должен быть изменен на Suppport 2-ступенчатый Призыва
  • Внутренними объектами ASP.NET, такими как Request и Response являются not available when called from a background task launched with ThreadPool.QueueUserWorkItem.
  • Дросселирование на занятом сервере становится намного сложнее, если с каждым запросом задействовано несколько потоков.
  • сервер должен висеть на результатах до тех пор, пока клиент не подберет их (или вы не выберете их), которые могут съесть RAM, если результаты будут большими.
  • вы не можете передавать большие, промежуточные результаты обратно клиенту

Правда, в некоторых сценариях 2-метод подход может масштабироваться лучше и будет более устойчивым к сломанной сетевые соединения между клиентом и сервером. Если вам нужно забрать результаты за несколько часов позже, это нужно рассмотреть. Но ваши операции занимают всего несколько минут, и вы можете гарантировать, что клиент будет оставаться подключенным, учитывая сложность адъютационной функции 2-метода, я бы счел, что это последнее средство, которое будет использоваться, только если решение с одним методом не будет соответствуют вашим потребностям.

В любом случае, решение требует двух частей. Во-первых, вам нужно вызвать метод асинхронно с клиента. Во-вторых, вам нужно удлинить таймауты как на клиенте, так и на сервере. Я охватываю оба ниже.

Вызов ASMX Web Services Асинхронный

Для вызова веб-службы ASMX асинхронно из приложения командной строки, посмотрите на this article начиная с страницы 2. Он показывает, как вызвать веб-сервис асинхронно из Приложение .NET cilent, используя новый Event-Based Async Pattern. Обратите внимание, что старший .NET 1.0, описанный here, который полагается на методы BeginXXX/EndXXX на прокси, больше не рекомендуется больше, так как генератор прокси-сервера Visual Studio не создает эти методы. Лучше использовать шаблон, основанный на событиях, как указано выше.

Вот выдержка/адаптация из приведенных выше статей, так что вы можете получить представление о коде вовлеченной:

void KickOffAsyncWebServiceCall(object sender, EventArgs e) 
{ 
    HelloService service = new HelloService(); 
    //Hookup async event handler 
    service.HelloWorldCompleted += new 
     HelloWorldCompletedEventHandler(this.HelloWorldCompleted); 
    service.HelloWorldAsync(); 
} 

void HelloWorldCompleted(object sender, 
         HelloWorldCompletedEventArgs args) 
{ 
    //Display the return value 
    Console.WriteLine (args.Result); 
} 

удлиняет сервер и клиент таймауты

Чтобы предотвратить таймаут, http://www.dotnetmonster.com/Uwe/Forum.aspx/asp-net-web-services/5202/Web-Method-TimeOut имеет хорошая сводка о том, как настроить как таймауты клиента, так и сервера. Вы не указали в своем вопросе, если у вас есть метод на стороне сервера или только на стороне клиента вызов, поэтому ниже отрывок охватывает оба случая:

там есть два setttings, которые влияют на тайм-аут вебсервис вызова поведение:

** настройка на стороне сервера httpruntime Тайм-аут The WebService ASP.NET, это настраивается через следующий элемент:

httpRuntime элемент (схема параметров ASP.NET)
http://msdn2.microsoft.com/en-us/library/e1f13641.aspx

< Конфигурация> < system.web>
< httpRuntime .............
ExecutionTimeout = "45"
........... .... /> < /system.web> </конфигурация>

Кроме того, убедитесь, что вы установили < компиляции отлаживать = "ложных" /> так, чтобы сделать работу таймаута правильно ,

** Если вы используете wsdl.exe или VS IDE «добавить webreference» сгенерированный прокси для вызова методов веб-сервиса, есть также тайм-аут настройки на прокси-класса клиента (производный от класса SoapHttpClientProtocol) , Это свойство «Тайм-аут» происходит от «WebClientProtocol» класса:

WebClientProtocol.Timeout собственности http://msdn2.microsoft.com/en-us/library/system.web.services.protocols.webclientprotocol.timeout.aspx

Таким образом, вы можете рассмотреть вопрос о корректировке эти два значения в соответствии со сценарием вашего приложения. Вот это бывший нить также упомянул об этом:

http://groups.google.com/group/microsoft.public.dotnet.framework.webservices/browse_thread/thread/73548848d0544bc9/bbf6737586ca3901

Обратите внимание, что я настоятельно рекомендую сделать ваши таймауты достаточно долго, чтобы охватить вашу самую длинную операцию (плюс достаточное количество буфера, чтобы быть в безопасности, должны получить все медленнее) но я бы не рекомендовал полностью отключать таймауты. Как правило, плохая практика программирования позволяет неограниченное время ожидания, так как ошибочный клиент или сервер может навсегда отключить другой. Вместо этого достаточно просто сделать тайм-ауты - и убедитесь, что вы регистрируете экземпляры, где ваши клиенты или серверы тайм-аут, поэтому вы можете обнаружить и диагностировать проблему, когда это произойдет!

Наконец, чтобы повторить комментарии выше: для нового кода лучше всего использовать WCF. Но если вы застряли с использованием веб-служб ASMX, это решение должно работать.

3

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

Если вам нужен результат (в конце концов) или необходимо проверить состояние операции, это будет работать не очень хорошо. То, что ваш метод должен делать в этом случае, - это запустить работу в фоновом потоке, а затем сразу же вернуть идентификатор, который можно использовать в другом веб-методе для поиска статуса.

Так что-то вроде этого:

public enum JobStatus { Running, Completed, Failed }; 

public class MyService : WebService 
{ 
    [WebMethod] 
    public int BeginJob() 
    { 
     int id = GetJobID(); 
     // Save to a database or persistent data source 
     SaveJobStatus(id, JobStatus.Running); 
     ThreadPool.QueueUserWorkItem(s => 
     { 
      // Do the work here 
      SaveJobStatus(id, JobStatus.Completed); 
     } 
     return id; 
    } 

    [WebMethod] 
    public JobStatus GetJobStatus(int id) 
    { 
     // Load the status from database or other persistent data source 
     return (...) 
    } 
} 

Это один способ, чтобы начать работу, и другой способ, чтобы проверить его состояние. Клиенту периодически приходится проводить опрос. Это не очень хорошая система, но у вас нет много вариантов с ASMX.

Конечно, если вам нужен ответ от этой операции, гораздо лучше использовать. WCF дает вам callback contracts, который вы можете использовать для начала односторонней операции и подписываться на уведомление, когда эта операция будет завершена, что исключает необходимость опроса выше.

Итак, подытоживая все, что:

  • Если вам не нужны какие-либо обновления ответа или состояния, просто используйте IsOneWay = true.

  • Если вам нужны обновления и вы можете использовать WCF со стороны службы, используйте это с контрактом обратного вызова. В любом случае вы должны использовать WCF для новых проектов веб-сервисов.

  • Если вам нужны обновления и не можете использовать WCF, выполните работу в фоновом потоке и внедрите периодическую систему опроса с дополнительным веб-методом проверки состояния.