使用TPL的协作多任务处理
我们正在移植一个建模应用程序,这个程序使用IronPython脚本来执行建模过程中的自定义操作。现在的应用程序会在不同的线程中执行每个Python脚本,并采用协作模型。我们想把它移植到TPL(任务并行库),但首先想测量一下上下文切换的情况。
目前我们有的内容:
- 一个任务队列
- 这个队列中的每个任务执行一个IronPython脚本
- 在IronPython脚本中,我们调用一个C#类的方法,这个方法是一个同步点,应该把任务(IronPython的执行)转为等待状态
我们想要做的事情:
- 我们想创建一个无限循环,遍历任务队列
- 当我们获取到一个任务时,尝试执行它
- 在Python脚本中,我们想调用C#的方法,把这个脚本转为等待状态,但不从队列中移除它。
- 在下一次循环中,当我们获取到另一个任务时,检查它是否处于等待状态。如果是,就把它唤醒并尝试执行。
- 在任何时刻,我们应该只有一个活跃的任务
- 最后,我们想测量每秒能执行多少个任务
我不太确定这是否与协作多任务有关?我们在考虑自定义的任务调度器,这样做是否合适?或者有没有人知道更好的解决方案?
谢谢。
更新:
好吧,比如说,我有这样的代码:
public class CooperativeScheduler : TaskScheduler, IDisposable
{
private BlockingCollection<Task> _tasks;
private Thread _thread;
private Task _currentTask;
public CooperativeScheduler()
{
this._tasks = new BlockingCollection<Task>();
this._thread = new Thread(() =>
{
foreach (Task task in this._tasks.GetConsumingEnumerable())
{
this._currentTask = task;
TryExecuteTask(this._currentTask);
}
}
);
this._thread.Name = "Cooperative scheduler thread";
this._thread.Start();
}
public void SleepCurrentTask()
{
if (this._currentTask != null)
{
// what to do here?
}
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return this._tasks.ToArray<Task>();
}
protected override void QueueTask(Task task)
{
// No long task
this._tasks.Add(task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
throw new NotImplementedException();
}
public void Dispose()
{
this._tasks.CompleteAdding();
this._thread.Join();
}
}
自定义任务调度器,它有一个线程用于任务执行,还有一个字段用于当前正在运行的任务。此外,它有一个方法叫做
客户端代码很简单:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Application app = Application.Create();
Task task = Task.Factory.StartNew(() =>
{
app.Scheduler.SleepCurrentTask();
},
tokenSource.Token, TaskCreationOptions.None, app.Scheduler);
}
也许有人有更好的想法?
1 个回答
2
听起来你可以考虑使用生产者/消费者模式,这个模式在.NET 4中已经内置在一些集合里了。
你可以查看微软提供的这本免费PDF的第55页,里面有相关内容,链接在这里:并行编程模式