Communication with an object within a task

I want to know how or even if it is necessary in my case to communicate with an object launched inside a task.

I have a set of processes that are generic objects that do some lengthy monitoring and computation:

private IEnumerable<IService> _services;

      

Since they are based on a common interface, they implement the "doSomeWork" method. Therefore, you can call this DoWork method for arguments.

I want all of these methods to run in a separate task space rather than sequentially, so I run the task list at the same visibility 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 startervice method basically starts monitoring and working on a single item:

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

      

Services also have a "stop" and "continue" method, which leads to my question. At the core of using tasks, I would try to find a way to affect service with a task using an event or delegate, pause / stop the task, or just call these methods on an element from the external _services collection?

eg:.

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

      

If this is the first one, then how should I raise the event inside the task from the outside, or should I control the external flag?

+3


source to share


2 answers


You can use CancellationToken

as a one-time event:

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

      



Hopefully this will work with your specific service API. Note that the token can run before the service starts, as well as after you are done.

+2


source


Complete solution code: 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 start my task and set of services:

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 method.

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

      

0


source







All Articles