Веб-служба C # .NET асинхронно - PullRequest
4 голосов
/ 02 июня 2011

Я пытаюсь реализовать API, который выполняет некоторые очень длинные задачи с использованием веб-службы. В основном я хочу, чтобы веб-служба запускала поток, выполняющий длинную задачу, и оставляла его работающим до завершения. Проблема в том, что это API, я хочу, чтобы он был кроссплатформенным. Итак, мои вопросы следующие:

  • Можно ли совершать асинхронные вызовы, которые не требуют, чтобы клиент находился в .NET Framework? (Похоже, что для начала / конца фреймворка требуется, чтобы я возвращал объект .NET IASyncResult). Если да, то как это можно сделать? Полностью однозначный пример кода был бы поразительно полезен.
  • Поскольку в веб-сервисе нет сохранения состояния, можно ли позже восстановить этот поток? В случае, если клиент хочет отменить процесс, это будет очень важно.

Ответы [ 4 ]

4 голосов
/ 02 июня 2011

Хорошо, вернитесь на секунду.

Если вы хотите, чтобы люди могли вызывать асинхронно, тогда они контролируют, а вы просто отвечаете. Если вы хотите, чтобы асинхронная работа выполнялась на вашей стороне, то вам нужно установить другую схему. Один шаблон состоит в том, чтобы установить метод, который вызывает работу, а затем другой метод, чтобы увидеть статус работы. Первый метод возвращает некоторый тип токена / идентификатора, который можно использовать для проверки состояния другого вызова. Затем у вас есть третий способ получить результаты. Это все зависит от клиента.

Теоретически вы можете настроить механизм обратного вызова, но клиент должен иметь средство для получения ответа, что является услугой на его стороне. Это более сложный и менее "публичный API" по своей природе, но он может работать с клиентами.

Неоднородная природа системы не должна быть фактором. И вы можете установить оба шаблона, чтобы клиенты, у которых есть веб-служба, которая может принять ответ, могли сработать и забыть, в то время как другие опрашивают.

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

while(thread.NoComplete())
{
   pollTheCrapOutofService();
}

Если вы можете обойти гетерогенные среды (открытые стандарты и др.) И можете форсировать .NET, у вас есть другие варианты, как упоминал Крейг.

2 голосов
/ 02 июня 2011

Это хорошее место для начала:

http://msdn.microsoft.com/en-us/library/aa480516.aspx

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

Из примера кода, несколько измененного, чтобы дать вам представление о том, что вам нужно сделать (я не ожидаю, что это скомпилируется):

[WebService]
public class AsyncWebService : System.Web.Services.WebService
{
public delegate string LengthyProcedureAsyncStub(
    int milliseconds, MyState state);

public string LengthyProcedure(int milliseconds, MyState state) 
{ 
    while(state.Abort == false)
    {
          //Do your work.  Check periodically for an abort
    }
    return state.Abort ? "Aborted" : "Success"; 
}

//This state object is what you can use to track invocations of your method
//You'll need to store it in a thread safe container.  Add it to the container in the Begin method and remove it in the end method.  While it's in the container other web methods can find it and use it to monitor or stop the executing job.
public class MyState 
{ 
    public Guid JobID = Guid.NewGuid();
    public object previousState; 
    public LengthyProcedureAsyncStub asyncStub; 
    public bool Abort = false;
}

[ System.Web.Services.WebMethod ]
public IAsyncResult BeginLengthyProcedure(int milliseconds, 
    AsyncCallback cb, object s)
{
    LengthyProcedureAsyncStub stub 
        = new LengthyProcedureAsyncStub(LengthyProcedure);
    MyState ms = new MyState();
    ms.previousState = s; 
    ms.asyncStub = stub;
    //Add to service wide container
    return stub.BeginInvoke(milliseconds, cb, ms);
}

[ System.Web.Services.WebMethod ]
public string EndLengthyProcedure(IAsyncResult call)
{
    //Remove from service wide container
    MyState ms = (MyState)call.AsyncState;
    return ms.asyncStub.EndInvoke(call);
}

[WebMethod]
public void StopJob(Guid jobID)
{
     //Look for the job in the service wide container
     MyState state = GetStateFromServiceWideContainer(jobID);
     state.Abort = true;
}
}

Насколько клиентобеспокоены тем, что они вызывают веб-метод LenghtyProcedure, который не вернется, пока работа не будет завершена.

1 голос
/ 02 июня 2011

Можно ли совершать асинхронные вызовы, не требующие подключения клиента к .NET Framework?(Похоже, что для начала / конца фреймворк требует, чтобы я возвращал объект .NET IASyncResult). Если да, то как это можно сделать?

Предоставьте REST API своим клиентам.Затем вам просто нужен слой кода, который транслируется между вашими асинхронными объектами .NET и службой REST.

Поскольку в веб-службе нет сохранения состояния, можно ли впоследствии восстановить этот поток?

Можно предоставить метод REST, который возвращает состояние операции, идругой метод REST, который отменяет вашу асинхронную операцию.

Для длительных операций я обычно настраиваю службу Windows с ThreadPool.Здесь вы можете открыть свой API-интерфейс IAsync.

Самый простой способ представить API-интерфейс REST на сервере IIS - использовать простое приложение ASP.NET MVC.Вы можете выполнять свои длительные асинхронные процессы непосредственно из методов контроллера.

1 голос
/ 02 июня 2011

Для этого мы используем службы AppFabric Workflow.

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

Постоянство включено бесплатно (если вы настроили SQL Server), как и мониторинг и администрирование, и клиенты .NET генерируются автоматически.

Один потенциальный недостаток: вам нужны IIS 7+ и .NET4.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...