我想知道在我的情况下如何或者甚至是否需要与在Task中运行的对象进行通信。
我有一组进程,这些进程是执行一些长时间运行的监视和计算的通用对象:
private IEnumerable<IService> _services;
由于它们基于通用接口,因此它们实现了“doSomeWork”的方法。因此,对于参数sakes,我们可以调用该方法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集合调用这些方法?
e.g:
_services.ForEach(item => item.Stop());
如果是前者,那么如何从外面提升任务内部的事件,还是应该监控外部标志?
答案 0 :(得分:2)
您可以将CancellationToken
用作一次性事件:
token.Register(() => item.Stop())
希望这适用于您的特定服务&#34; API。请注意,令牌可以在服务启动之前以及完成之后触发。
答案 1 :(得分:0)
完整的解决方案代码是: 我的新容器类
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());
}