Отмена длительной задачи над WCF от клиента

У меня установлен сервис WCF для PerCall

Я хотел бы знать, как я могу отправить вызов Start от клиента, чтобы запустить длительный процесс, и отправить команду Cancel, чтобы отменить его.

Моя служба WCF выглядит примерно так

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class Service1 : IService1
    {

        CancellationTokenSource cancelToken = new CancellationTokenSource();



        public void Start()
        {

            var compute = Task.Factory.StartNew(StartLongRunningTask, cancelToken.Token);
        }

        public void Stop()
        {

            cancelToken.Cancel();
        }

            private void StartLongRunningTask()
            {
                  //process here

            }

}

Я предполагаю, что проблема здесь в том, что каждый раз, когда на сервер поступает вызов, он обрабатывается как новый запрос.

Итак, как следует запускать и отменять длительную задачу в WCF?

РЕДАКТИРОВАТЬ: я размещаю его как службу Windows


person Null Reference    schedule 10.03.2013    source источник
comment
Вам нужно будет хранить токен вне класса WCF. Хост может быть перезапущен между запросами WCF, в зависимости от хоста; так что вам, возможно, придется сначала разобраться с этим. Скорее всего, вам понадобится какой-то другой токен, чтобы найти источник токена отмены, который вы передаете в контракт Stop.   -  person Peter Ritchie    schedule 10.03.2013
comment
Когда вы говорите за пределами класса WCF, вы имеете в виду создание другой dll для обработки токенов и ссылки на эту dll в проекте WCF? Разве это не будет по-прежнему?   -  person Null Reference    schedule 11.03.2013


Ответы (2)


У меня установлен сервис WCF для PerCall

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

Ага, именно это вы и говорите. Если можете, просто измените на InstanceContextMode.PerSession; тогда вы можете делать то, что пытаетесь сделать (при условии, что вы размещаете на собственном хостинге).

Если вы не можете этого сделать, вам придется разработать более сложное решение, как прокомментировал @PeterRitchie. Во-первых, ваш хост: IIS не предназначен для длительных операций, независимых от запросов, поэтому я предполагаю, что вы размещаете на собственном хостинге. Затем вам понадобится форма токена (например, GUID), которая будет выступать в качестве идентификатора для длительной операции. Ваш Start метод выделит GUID и CancellationTokenSource и запустит операцию, а ваш Stop метод примет GUID и будет использовать его для поиска CancellationTokenSource и отмены операции. Вам понадобится общий (статический, потокобезопасный) словарь, который будет выполнять функцию поиска.

Если ваш хост - IIS, тогда ваше решение становится более сложным ... :)

Во-первых, вам понадобится серверная часть, которая не размещена в IIS. Обычно можно выбрать рабочую роль Azure или службу Win32. Затем вам понадобится надежный механизм связи: очередь Azure, MSMQ, WebSphere и т. Д. Затем вы можете создать свою службу WCF поверх IIS, чтобы метод Start генерировал идентификатор GUID и помещал сообщение в очередь для запуска. обработка. Метод Stop принимает GUID и помещает сообщение в очередь для отмены обработки. Вся остальная логика переносится на серверную службу.

person Stephen Cleary    schedule 11.03.2013
comment
Да, моя служба размещена в службе Windows - person Null Reference; 11.03.2013
comment
Итак, мне нужен статический словарь с атрибутом [ThreadStatic], в котором хранится guid и объект отмены, и вытаскивать его из словаря, когда клиент в следующий раз отправляет вызов? - person Null Reference; 11.03.2013
comment
ThreadStatic не работал. Нет гарантии, что отменяющий вызов будет выполняться на сервере в том же потоке, что и исходный вызывающий поток. Стивен имел в виду словари параллелизма. Однако я серьезно предлагаю вам взглянуть на мое решение (которое было отклонено). IFF вы используете .net 4.5 от начала до конца. - person Aron; 11.03.2013
comment
@ Арон прав. Я имел в виду static ConcurrentDictionary<Guid, CancellationTokenSource>. - person Stephen Cleary; 11.03.2013

Судя по тому, как вы спросили, клиент, похоже, знает об асинхронном характере запроса.

Пункты @StephenCleary и @ PeterRitchie превосходны, но ваш первый шаг - переделать вашу службу / контракт, чтобы правильно реализовать асинхронную службу и добавить средства обратной связи (клиенту) некоторой информации / дескриптора для длительной операции.

Framework содержит несколько парадигм асинхронного программирования (уже :-)), но когда дело доходит до WCF, вы как бы прибегаете к Как: реализовать асинхронную операцию службы

Это обеспечит некоторую инфраструктуру, но не обязательно возможность автоматически отменять операцию.

Говоря строго об отмене (поскольку это ваш вопрос): вам придется продлить все, что ваше решение в конечном итоге будет для отмены. Как минимум, вам нужно добавить необходимую логику к своему сервисному «worker» для отслеживания и соблюдения токена отмены.

Другие соображения, с которыми вы можете столкнуться: возврат результата при отмене; отмена задачи, которая была завершена (кто из вас обновил 1000000 записей к моменту поступления запроса на отмену); обработка исключений (при программировании на основе задач исключения не генерируются, а объединяются в Задаче или в другом «средстве», которое вы используете для описания текущей операции).

person G. Stoynev    schedule 11.03.2013