我正在asp.net mvc应用程序中运行CPU绑定任务。一些用户可以“订阅”此任务,应将完成情况通知他们。但是,当任务没有订阅者时,必须将其取消。任务通过ajax请求开始,并在调用.abort()方法时取消。在控制器中,我将CancellationToken作为确定取消的参数。
问题在于,当一个订户呼叫中止(取消订阅)时,尽管其他用户正在等待结果,但链接的令牌会取消任务。检查某些条件后如何取消CancellationToken?每次循环迭代后,我都无法检查IsCancellationRequested属性,因为我包装了非异步方法。
任务完成后,将通过SignalR通知用户。我试图实现ConcurrentDictionary在取消任务是否有订阅者之前进行检查。
private async Task<Diff> CompareAsync(Model modelName, CancellationToken ct)
{
try
{
return await Task.Factory.StartNew(() =>
{
ct.ThrowIfCancellationRequested();
return _someServiceName.CompareLines(modelName.LinesA, modelName.LinesB, ct);
}, ct, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
//do some things
}
}
我需要这样的东西,但不能提出任何(不难看)的想法:
private async Task<Diff> CompareAsync(Model modelName, CancellationToken ct)
{
try
{
return await Task.Factory.StartNew(() =>
{
using (var source = new CancellationTokenSource())
{
if (ct.IsCancellationRequested && CompareService.SharedComparison.TryGetValue(modelName.Hash, out var usersCount) && usersCount < 2)
{
source.Cancel();
}
return _someServiceName.CompareLines(modelName.LinesA, modelName.LinesB, source.Token);
}
}, ct, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
//do some things
}
}
答案 0 :(得分:0)
您将必须保持线程安全订阅者计数(最有可能使用lock
),并且仅在令牌0
时取消令牌。
private int _subscribers;
private object _sync = new object();
private AddSubscribers()
{
Lock(_sync )
{
// do what ever you need to do
_subscribers++;
}
}
private RemoveSubscribers()
{
Lock(_sync )
{
// do what ever you need to do
_subscribers--;
if(_subscribers <= 0)
{
// cancel token
}
}
}
注意 :显然,这不是一个完整的解决方案,给想象力留下了很多印象