与任务中的对象通信
本文关键字:对象 通信 任务 | 更新日期: 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());
}