C#发送消息到任务

时间:2018-08-10 15:46:14

标签: c# multithreading task

我有一个程序,可以创建许多任务,每个任务运行一个无限的操作循环(至少直到被用户停止为止)

public class SomeTask
{
    private bool CanLoop;

    public SomeTask()
    {
        CanLoop = true;
    }

    public void Execute()
    {
        // some loop initialization

        while (CanLoop)
        {
            // DoSomething(TM)
        }

        // some loop finalization
    }

    public void Stop()
    {
        CanLoop = false;
    }
}

public class Launcher
{
    private readonly CancellationTokenSource _cancellationTokenSource;

    public Launcher()
    {
        _cancellationTokenSource = new CancellationTokenSource();
    }

    public void Launch()
    {
        var _tasks = new List<Task>();
        var n = 10; // number of tasks to launch, may vary
        for (var i = 0; i < n; i++)
        {
            var item = new SomeTask();
            var token = _cancellationTokenSource.Token;
            var task = Task.Run(() =>
            {
                token.Register(() => item.Stop());
                item.Execute();
            }
            _tasks.Add(task);
        }
    }
}

代码非常简单,我执行了Launcher类的Launch方法的调用,所有任务开始运行,直到我决定停止它们。到目前为止一切都很好。

问题是:我需要主类(Launcher)来接收来自外部源的事件(通过signalR客户端,我可以做到)并将其传播到正在运行的任务中,而无需停止并重新启动它们。

我可以侦听每个任务中的事件,但这意味着每个任务的信号连接都不高效(在示例中,我启动了10个任务,它们可能是2个,也可能是100个,这取决于外部因素);因此,考虑到所有任务的事件源都是相同的,最好的方法应该是将消息发送到任务的单个侦听器。

类似这样的东西

public class SomeTask
{
    private bool CanLoop;
    private bool DoSpecificAction;

    public SomeTask()
    {
        CanLoop = true;
        DoSpecificAction = false;
    }

    public void Execute()
    {
        // some loop initialization

        while (CanLoop)
        {
            if (DoSpecificAction)
            {
                // do some specific action
                DoSpecificAction = false;
            }
            // DoSomething(TM)
        }

        // some loop finalization
    }

    public void Stop()
    {
        CanLoop = false;
    }

    public void SpecificAction()
    {
        DoSpecificAction = true;
    }
}

public class Launcher
{
    private readonly CancellationTokenSource _cancellationTokenSource;

    public Launcher()
    {
        _cancellationTokenSource = new CancellationTokenSource();
    }

    public void Launch()
    {
        var _tasks = new List<Task>();
        var n = 10; // number of tasks to launch, may vary
        for (var i = 0; i < n; i++)
        {
            var item = new SomeTask();
            var token = _cancellationTokenSource.Token;
            var task = Task.Run(() =>
            {
                token.Register(() => item.Stop());
                item.Execute();
            }
            _tasks.Add(task);
        }
    }

    public void SomeExternalEvent()
    {
        // this is where i should send event to tasks
        foreach (var task in _tasks)
        {
            task.SpecificAction();
        }
}

这可能吗?还是我唯一的选择是每个任务只有一个侦听器?


修改

感谢tobeypeters关于使用BufferBlock的建议。我做了一些测试,然后想出了一个可以运行的测试应用程序。如果有人感兴趣,可以在github

上找到测试应用程序代码

0 个答案:

没有答案