与任务中的对象通信

Communicate with object inside a Task

我想知道在我的情况下如何甚至是否需要与任务中的对象运行进行通信。

我有一个进程集合,它们是执行一些长时间 运行ning 监视和计算的通用对象:

private IEnumerable<IService> _services;

由于它们基于一个公共接口,因此它们实现了 "doSomeWork" 的方法。因此,为了争论起见,让我们调用该方法 DoWork。

我希望这些方法全部 运行 在一个单独的任务 space 中而不是按顺序阻塞,所以我在与 运行 类似的范围级别上旋转一个任务列表程序的一部分。

private List<Task> ProcessTask = new List<Task>();
private CancellationTokenSource tokenSource = new CancellationTokenSource();
private CancellationToken token;

private void startAll()
{
    token = tokenSource.Token;
    ProcessTask = _services.Select(service => Task.Factory.StartNew(
    () => StartService(service),
    token, 
    TaskCreationOptions.LongRunning,
    TaskScheduler.Current)).ToList();
}

startservice 方法基本上启动监视并处理单个项目:

private void StartService(IService plugin)
{
   ...
   ...
   plugin.DoWork();
   ...
   ...
}

这些服务也有一个 "stop" 和 "continue" 的方法,这引出了我的问题。在使用任务的核心,我最好尝试找到一种方法来影响服务,通过使用事件或委托和 pausing/stopping 任务来影响服务,或者只是在外部 _services 集合中的项目上调用这些方法?

例如:

_services.ForEach(item => item.Stop());

如果是前者,那么我如何从外部引发任务内部的事件,或者我应该监视外部标志?

您可以将 CancellationToken 用作一次性事件:

token.Register(() => item.Stop())

希望这将适用于您的特定 "service" API。请注意,令牌可以在服务启动之前触发,也可以在您完成后触发。

完整的解决方案代码为: 我的新容器 class

internal class ServiceContainer
{
    /// <summary>
    /// Process service which runs the monitor
    /// </summary>
    public IService ServiceProcess { get; private set; }

    /// <summary>
    /// Cancellation token used to cancel the operation
    /// </summary>
    public CancellationTokenSource CancelTokenSource { get; private set; }

    internal ProcessContainer(IService plugin)
    {
        this.PluginProcess = plugin;
        CancelTokenSource = new CancellationTokenSource();
    }
}

然后创建服务包装器列表:

serviceWrapperList = _plugins.Select(service => new ServiceContainer(service)).ToList();

然后我得到我的任务运行和基础服务集:

ProcessTaskList = serviceWrapperList.Select(serviceSet => Task.Factory.StartNew(
            () =>
            {
                IService service = serviceSet.ServiceProcess;
                CancellationToken token = serviceSet.CancelTokenSource.Token;
                StartService(service);
                token.Register(() => StopPlugin(service));
            },
            serviceSet.CancelTokenSource.Token,
            TaskCreationOptions.LongRunning,
            TaskScheduler.Current)).ToList();

我终于有了停止所有方法。

    protected void StopAllServices()
    {
        ProcessTaskList.ForEach(f => f.CancelTokenSource.Cancel());
    }