Reputation: 460
I want to know how or even if its required in my case to communicate with an object running inside a Task.
I have a collection of processes, which are generic objects that perform some long running monitoring and calculating:
private IEnumerable<IService> _services;
Since they are based on a common interface they implement a method to "doSomeWork". So for arguments sakes lets call that method DoWork.
I want these methods all to run in a separate task space and not block sequentially, so I am spinning up a task list at a similar scope level to run this part of the program.
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();
}
The startservice method basically starts the monitoring and work on the individual item:
private void StartService(IService plugin)
{
...
...
plugin.DoWork();
...
...
}
The services also have a method to "stop" and "continue", which leads to my question. In the heart of using tasks would I be best trying to find a way of influencing the service from withing the task using an event or delegate and pausing/stopping the task or just calling these methods on the item from the external _services collection?
e.g.:
_services.ForEach(item => item.Stop());
If it is the former then how do I raise an event inside the task from out side, or should I monitor an external flag?
Upvotes: 3
Views: 659
Reputation: 460
Complete solution code is: My new container 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();
}
}
Then create a list of service wrappers:
serviceWrapperList = _plugins.Select(service => new ServiceContainer(service)).ToList();
Then I get my task running and based service set:
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();
Finally I have my stop all method.
protected void StopAllServices()
{
ProcessTaskList.ForEach(f => f.CancelTokenSource.Cancel());
}
Upvotes: 0
Reputation: 171178
You can use the CancellationToken
as a one-shot event:
token.Register(() => item.Stop())
Hopefully, this will work with your particular "service" API. Note, that the token can fire before the service starts and also after you are done.
Upvotes: 2