Мы портируем приложение для моделирования, которое использует скрипты IronPython для пользовательских действий в процессе моделирования. Существующее приложение выполняет каждый скрипт Python в отдельном потоке и использует для этого модель сотрудничества. Теперь мы хотим перенести его на TPL, но сначала мы хотим измерить переключение контекста.
,
В основном то, что мы имеем сейчас:
Task
s очередь
- каждый
Task
из этой очереди выполняет один скрипт IronPython
- Внутри скрипта IronPython мы вызываем метод класса C #, который является точкой синхронизации и должен перевести
Task
(выполнение IronPython) в состояние ожидания
Что мы хотим сделать:
- Мы хотим сделать бесконечный цикл, который будет перебирать очередь
Task
s
- когда мы получаем один
Task
, мы пытаемся выполнить его
- В PythonScript мы хотим вызвать метод C # и перевести этот скрипт в состояние ожидания. но не удаляйте его из очереди.
- На следующей итерации, когда мы получаем еще
Task
, мы проверяем, находится ли она в состоянии ожидания. если это так, мы просыпаемся и пытаемся выполнить.
- В каждый момент у нас должен быть только один активный
Task
- И, наконец, мы хотим измерить, сколько
Task
мы могли бы выполнить в секунду
Я действительно не знаю, это что-то о совместной многозадачности?
Мы думаем о кастомах TaskScheduler
, это хороший подход? Или кто-то знает лучшее решение?
Спасибо.
Обновлен:
Хорошо, например, у меня есть такой код:
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();
}
}
Пользовательский планировщик задач, у него есть одно _thread
для выполнения задачи и _currentTask
поле для запуска задачи, также в этом методе есть SleepCurrentTask
. В этом методе я хочу приостановить текущее выполнение задачи, но я не знаю как.
Код клиента прост:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Application app = Application.Create();
Task task = Task.Factory.StartNew(() =>
{
app.Scheduler.SleepCurrentTask();
},
tokenSource.Token, TaskCreationOptions.None, app.Scheduler);
}
Может быть, у кого-то есть идеи получше?