Как указано выше. Невозможно пересечь границу службы и отменить на стороне сервера.
Если вы хотите отменить задачу на стороне клиента, вы можете использовать метод расширения WithCancellation
из Microsoft.VisualStudio.Threading. ThreadingTools
Это часть Visual Studio SDK , или вы также можете получить ее из Nuget .
CancellationTokenSource ct = new CancellationTokenSource();
ct.CancelAfter(20000);
var asyncTask = _myService.LongOperationAsync();
await asyncTask.WithCancellation(ct.Token);
После редактирования вопроса я вижу, что допустимо отмену логического уровня. Если это так, можно попробовать следующий алгоритм.
1) Создайте службу с помощью InstanceContextMode=InstanceContextMode.PerSession
, чтобы гарантировать, что у вас есть тот же экземпляр службы для обслуживания последующих запросов.
2) для запуска новых сеансов используйте служебные операции, отмеченные OperationContract(IsInitiating = True)
3), создайте в качестве члена службы. не статично. это будет состояние обслуживания
CancellationTokenSource ct = new CancellationTokenSource();
4) внутри каждого метода обслуживания вам придется начинать новые вычисления внутри задач и помещать токен отмены в качестве параметра для этой задачи.
[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface ICalculator
{
[OperationContract(IsInitiating = True)]
Bool Begin()
[OperationContract(IsInitiating = false)]
double Add(double n1, double n2)
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculator
{
CancellationTokenSource cts = new CancellationTokenSource();
public double Add(double n1, double n2)
{
var cancellationToken = cts.Token;
var t = Task<double>.Factory.StartNew(() => {
// here you can do something long
while(true){
// and periodically check if task should be cancelled or not
if(cancellationToken.IsCancellationRequested)
throw new OperationCanceledException();
// or same in different words
cancellationToken.ThrowIfCancellationRequested();
}
return n1 + n2;
}, cancellationToken);
return t.Result;
}
public Bool Begin(){}
}
Вот краткое описание сессий WCF .
Все примеры только с моей головы, не пробовали, если они действительно работают. Но вы можете попробовать.