与任务中的对象通信

本文关键字:对象 通信 任务 | 更新日期: 2023-09-27 17:57:00

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

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

private IEnumerable<IService> _services;

由于它们基于一个通用接口,因此它们实现了"doSomeWork"的方法。因此,为了参数的缘故,让我们称该方法为DoWork。

我希望这些方法都在单独的任务空间中运行,而不是按顺序阻止,因此我在类似的范围级别启动任务列表以运行程序的这一部分。

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();
   ...
   ...
}

这些服务也有"停止"和"继续"的方法,这导致了我的问题。 在使用任务的核心,我是否最好尝试找到一种方法来影响服务,方法是使用事件或委托在任务中暂停/停止任务,或者只是从外部_services集合中对项目调用这些方法?

例如:

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

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

与任务中的对象通信

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

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

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

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

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());
    }