У меня есть метод API, который работает в фоновом режиме (асинхронный) в течение ~ 6 минут.Я хочу разрешить пользователю отменить его из другого запроса API.
Например,
/api/credits/post/25
запустит фоновую задачу и немедленно возвратит ответ OK.
/api/credits/stop/25
прекратит запуск фоновой задачи.
мой текущий код.
API
[Route("api/[controller]")]
public class CreditController : Controller
{
private readonly CreditService _creditService;
public CreditController (CreditService creditService)
{
_creditService = creditService;
}
[HttpPost("[action]")]
public string Post(int id)
{
if (_creditService.Instances.Any(p => p.ID == id))
return "already running " + id;
_creditService.Post(id, (s,e) =>
{
// sending realtime changes to user using SignalR.
// so that they will see progress and whats running in background
});
return "started " + id;
}
[HttpPost("[action]")]
public string Stop(int id)
{
var instance = _creditService.Instances.SingleOrDefault(p => p.ID == id));
if (instance == null)
return id + " is not running";
instance.CancelToken.Cancel();
return id + " stoppped";
}
}
Служба
public class CreditService
{
public static List<CreditService> Instances = new List<CreditService>();
public Status<object> Status = new Status<object>();
public CancellationTokenSource CancelToken = new CancellationTokenSource();
public Task Post(int id, PropertyChangedEventHandler handler = null)
{
Instances.Add(this);
if (handler != null) Status.PropertyChanged += handler;
return Task.Factory.StartNew(() =>
{
try
{
// long running task
}
catch (Exception e)
{
Status.Error = e.Message ?? e.ToString();
}
finally
{
if (handler != null) Status.PropertyChanged -= handler;
Status.Clear();
CancelToken.Dispose();
Instances.Remove(this);
}
});
}
}
Это работает, как и ожидалось.но я хочу знать, является ли это хорошим подходом или есть другая лучшая альтернатива этому.
Также это не будет работать, если я использую балансировщик нагрузки и несколько экземпляров приложения.Как мне это исправить.