我有一个程序,可以创建许多任务,每个任务运行一个无限的操作循环(至少直到被用户停止为止)
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
上找到测试应用程序代码