Как общаться с фоновой задачей? - PullRequest
1 голос
/ 14 июля 2011

Я работаю над приложением, которое связывается с веб-сервисом. Клиентское приложение (silverlight-4.0) будет вызывать веб-сервис и запускать долгосрочную задачу. Поскольку для завершения задачи требуется некоторое время, она выполняется в отдельном потоке. (Использование System.Threading.Tasks.Task.Factory.StartNew () для создания отдельной задачи.) После запуска задачи вызов службы вернется с идентификатором, и соединение будет установлено.
Этот идентификатор должен быть чем-то, что мне нужно для определения задачи, чтобы я мог общаться с ней.

Следующий вызов, возможно, с использованием другого соединения, выполняется для проверки того, что задача уже выполнена. Для этого идентификатор является частью вызова. На сервере теперь необходимо проверить, выполняется ли еще задание или выполнено. Как мне снова найти эту задачу?


Служба работает в Azure, и из-за балансировки нагрузки второй вызов может выполняться в совершенно другой системе. Мне кажется, что это невозможно, но опять же ...
Этот Q относится к этому Q .

Ответы [ 3 ]

4 голосов
/ 14 июля 2011

Сделайте так, чтобы задача сообщала о своем состоянии в кеше таблицы / appfabric. Затем, когда кто-то опрашивает статус, просто считайте соответствующий статус для идентификатора задачи X из используемого механизма сохранения.

3 голосов
/ 14 июля 2011

Правильный способ сделать это - использовать связь на основе очереди. Причиной этого является масштабируемость . Вы хотите, чтобы «экземпляр» вашего сервиса принял запрос, и вы хотите, чтобы «экземпляр» возвратил результат клиенту, верно?

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

Создайте класс WorkerRequest, похожий на этот

public class WorkerRequest {
   string clientId;
   MyTaskEnum taskToPerform;
}

Запись в хранилище очереди (в моем производственном коде я использую оболочку, о которой я еще не писал в блоге, но планирую :)), добавьте запрос.

Пусть рабочий поток прослушивает эту очередь, а при получении запроса создает новый поток, чтобы завершить его. Когда вы закончите, напишите в табличное хранилище , указав в качестве ключей свою задачу и идентификатор клиента. Таким образом, вы всегда можете проверить статус (простой / GET / запрос к таблице) + разделение и масштабируемость уже решены.

Надеюсь, это поможет.

ОБНОВЛЕНИЕ: хотел объяснить немного больше, поэтому я решил обновить пост =)

Вы можете создать веб-службу WCF в «веб-роли», что я и сделал бы. Я писал о некоторое время назад. В той же роли вы создаете Worker . Вы делаете это, имея класс, который реализует RoleEntryPoint. Этот класс (находится в Microsoft.WindowsAzure.ServiceRuntime) выглядит следующим образом:

  public abstract class RoleEntryPoint
  {
    public virtual bool OnStart()
    {
      return true;
    }

    public virtual void Run()
    {
      Thread.Sleep(-1);
    }

    public virtual void OnStop()
    {
    }
  }

Вы просто реализуете цикл while (true) в Run, который запрашивает очередь на наличие новых сообщений для обработки. Когда такое сообщение получено , не создавайте новое , просто обработайте его. Если вы хотите масштабировать его, вы можете масштабировать с добавлением новых экземпляров. Очевидно, что это может быть дорогостоящим, так что на самом деле целесообразно создавать новую нить, но только до определенного предела, например, макс 5 потоков. Если в вашем пуле нет потоков, верните сообщение в очередь (вам нужно позвонить Complete(), когда закончите с сообщением, иначе оно не обязательно будет удалено). Его заберут позже или другой работник.

Итак, когда рабочий поток завершает работу, запишите результат в хранилище таблиц, и все готово.

2 голосов
/ 14 июля 2011

Задаче просто нужно сохранить где-то, что она выполнена, и сохранить результат, если ожидается результат.

Вы можете сохранить завершение с идентификатором задачи в хранилище таблиц или в SQL Azure, где бы вы ни были доступны.,Последующий опрос, чтобы увидеть, завершено ли оно, может просто проверить это хранилище и вернуть, заполнено ли оно или нет.

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

...