c# - 取消由 ASP.NET 启动的任务

标签 c# asp.net asp.net-mvc asynchronous signalr

背景

以下服务器端代码用于启动一个长时间运行的任务,该任务将通过 SignalR 将更新发布到 Web 前端。我在前端放置了一个按钮,然后我想根据用户的请求停止任务。

问题

当前端触发Stop方法时,tokenSource为空。我怀疑,这是因为它没有到达生成任务的 ChartHub 的同一个实例。

代码

using System;
...
using System.Security.Principal;

namespace dvvWeb.Hubs
{
public class ChartHub : Hub
{
    CancellationTokenSource tokenSource;
    CancellationToken ct;
    public void Start(string serverName, string dbName, string numberOfPoints, string pollingFrequency)
    {
        ConfigModel config = new ConfigModel();

        tokenSource = new CancellationTokenSource();
        ct = tokenSource.Token;

        config.Servername = HttpUtility.UrlDecode(serverName);
        config.DbName = HttpUtility.UrlDecode(dbName);
        config.Preferences.NumberOfPoints = int.Parse(numberOfPoints);
        config.Preferences.PollingFrequency = int.Parse(pollingFrequency);

        dvvGraphingModel graphingModel = new dvvGraphingModel();

        dvvGraphingHelper graphingHelper = new dvvGraphingHelper(graphingModel, config.Servername, config.DbName);

        graphingModel = graphingHelper.Tick(config.Preferences);

        var identity = WindowsIdentity.GetCurrent();

        Task.Run(() => workItemAsync(ct, graphingModel, graphingHelper, config, identity));
    }

    public void Stop()
    {
        tokenSource.Cancel();
    }


    private async Task<CancellationToken> workItemAsync(CancellationToken ct, dvvGraphingModel graphingModel, dvvGraphingHelper graphingHelper, ConfigModel configModel, WindowsIdentity identity)
    {
        await addDataAsync(ct, graphingModel, graphingHelper, configModel, identity);
        return ct;
    }

    private async Task<CancellationToken> addDataAsync(CancellationToken ct, dvvGraphingModel graphingModel, dvvGraphingHelper graphingHelper, ConfigModel configModel, WindowsIdentity identity)
    {

        try
        {
            while(!ct.IsCancellationRequested)
            {
                identity.Impersonate();
                Clients.Caller.addPointToChart(JsonConvert.SerializeObject(graphingModel));
                System.Threading.Thread.Sleep(configModel.Preferences.PollingFrequency * 1000);
                graphingModel = graphingHelper.Tick(configModel.Preferences);

            }
        }
        catch (TaskCanceledException tce)
        {
            Trace.TraceError("Caught TaskCanceledException - signaled cancellation " + tce.Message);
        }
        return ct;
    }
}
}

最佳答案

我会创建一个 ConcurrentDictionary<string, CancellationTokenSource>其中“string”是用户名/id 或者可能是

ConcurrentDictionary<IUserIdentity, CancellationTokenSource> .

嗯,这是在用户一次只能启动一个进程的情况下。

该字典将存在于 Hub 之外的单例类中。您的集线器将只是调用单例中方法的代理。

YourSingleton.Instance.Start(userId, serverName, dbName, numberOfPoints, pollingFrequency);

YourSingleton.Instance.Stop(userId);

然后,你可以这样做:

public void Stop(string userId)
{
    CancellationTokenSource tokenSource;
    if(dictionary.TryGetValue(userId, out tokenSource))
    {
        tokenSource.Cancel();
        dictionary.TryRemove(userId out tokenSource);
    }
}

关于c# - 取消由 ASP.NET 启动的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37795332/

相关文章:

c# - 临时文件包含对不带参数的构造函数的引用,而它不应该

javascript - 确保在过滤器运行之前填充 Observable 数组

asp.net-mvc - MVC View 中的条件语句

.Net - 使用 HttpClient 发布文件?

c# - 类型未知时比较数字类型

c# - 在 C# 数组中查找元素的连续重复并更改元素

c# - 在内联数据绑定(bind)上下文中使用扩展方法

css - ASP.Net MVC 音乐商店教程 CSS 布局问题

c# - Entity Framework 中的 System.Data.ProviderIncompatibleException

c# - 使用 c# 如何以编程方式检查我的报告服务器上是否存在文件夹