C# 根据条件取消长时间运行的任务

C# 根据条件取消长时间运行的任务,c#,asp.net-mvc,concurrency,C#,Asp.net Mvc,Concurrency,我正在asp.net mvc应用程序中运行cpu绑定任务。一些用户可以“订阅”此任务,并应通知他们任务已完成。但当任务没有订户时,它必须被取消。任务通过ajax请求启动,并在调用.abort()方法时取消。在控制器中,我将CancellationToken作为确定取消的参数 问题是,当其中一个订阅者调用abort(取消订阅)时,链接的令牌会取消任务,尽管其他用户正在等待结果。在检查某些条件后,如何取消CancellationToken?我无法在每次循环迭代后检查IsCancellationReq

我正在asp.net mvc应用程序中运行cpu绑定任务。一些用户可以“订阅”此任务,并应通知他们任务已完成。但当任务没有订户时,它必须被取消。任务通过ajax请求启动,并在调用.abort()方法时取消。在控制器中,我将CancellationToken作为确定取消的参数

问题是,当其中一个订阅者调用abort(取消订阅)时,链接的令牌会取消任务,尽管其他用户正在等待结果。在检查某些条件后,如何取消CancellationToken?我无法在每次循环迭代后检查IsCancellationRequested属性,因为我正在包装非异步方法

任务完成后,会使用信号器通知用户。我已经尝试实现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异步任务CompareAsync(Model modelName,CancellationToken ct)
{
尝试
{
return wait Task.Factory.StartNew(()=>
{
ct.ThrowIfCancellationRequested();
返回_someServiceName.CompareLines(modelName.LinesA、modelName.LinesB、ct);
},ct,TaskCreationOptions.LongRunning,TaskScheduler.Default)。配置等待(false);
}
捕获(操作取消异常)
{
//做一些事情
}
}
我需要这样的东西,但想不出任何(不难看的)主意:

private异步任务CompareAsync(Model modelName,CancellationToken ct)
{
尝试
{
return wait Task.Factory.StartNew(()=>
{
使用(var source=new CancellationTokenSource())
{
if(ct.iscancellationrequest&&compareseservice.SharedComparison.TryGetValue(modelName.Hash,out var userscont)&&userscont<2)
{
source.Cancel();
}
返回_someServiceName.CompareLines(modelName.LinesA、modelName.LinesB、source.Token);
}
},ct,TaskCreationOptions.LongRunning,TaskScheduler.Default)。配置等待(false);
}
捕获(操作取消异常)
{
//做一些事情
}
}

您必须维护线程安全的订户计数(最有可能使用
锁定
),并且只有当令牌为
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
       }
   }
}
private int\u用户;
私有对象_sync=新对象();
私有AddSubscribers()
{
锁定(同步)
{
//做你需要做的事
_用户++;
}
}
私人RemoveSubscribers()
{
锁定(同步)
{
//做你需要做的事
_订户--;

if(_)感谢您的快速回复。但取消时检查条件的主要问题。我只能通过ThrowIfCancellationRequested()取消任务,这不允许我检查订阅者的数量。我只是想在会话/缓存中保留令牌,以便在添加/删除订阅者时可以调用取消方法。但不确定令牌是否会链接together@Memskiy是的,我不太确定我是否理解这里的问题,但是我会把这个留给其他人知道这对你来说不是一个有效的解决方案
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
       }
   }
}