Estamos portando la aplicación de modelado, que utiliza scripts IronPython para acciones personalizadas en el proceso de modelado. La aplicación existente ejecuta cada script de Python en un hilo separado y usa un modelo cooperativo para esto. Ahora queremos conectarlo a TPL, pero primero queremos medir el cambio de contexto . Básicamente, lo que tenemos en este momento:Multitarea cooperativa usando TPL
Task
s cola- cada
Task
desde esta cola ejecuta un script IronPython - Dentro de la escritura IronPython llamamos a método de clase C#, que es punto de sincronización y debe transferir
Task
(ejecución IronPython) al estado de espera
Lo que queremos hacer:
- queremos hacer bucle infinito, que iterar a través de
Task
s cola - cuando tenemos una
Task
tratamos de ejecutarlo - En PythonScript queremos llamar a C Método # y transferir este script a estado de espera. pero no eliminarlo de la cola.
- En la siguiente iteración cuando obtenemos otra
Task
, comprobamos que está en estado de espera. si es así, lo despertamos e intentamos ejecutarlo. - En cada momento en que debe tener un solo activo
Task
- Y, por último que queremos medir cuántas
Task
podríamos ejecutar por segundo
que no se sabe muy bien que es algo acerca de la multitarea cooperativa? Estamos pensando en personalizar TaskScheduler
, ¿es un buen enfoque? ¿O alguien sabe mejor solución?
Gracias.
Actualizado:
Ok, así que por ejemplo, no tengo dicho código:
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();
}
}
programador de tareas personalizada, tiene uno _thread
para la ejecución de tareas y _currentTask
campo para ejecutar la tarea, también tiene SleepCurrentTask
en este método quiero suspender la ejecución actual de la tarea, pero no sé cómo.
El código de cliente es simple:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Application app = Application.Create();
Task task = Task.Factory.StartNew(() =>
{
app.Scheduler.SleepCurrentTask();
},
tokenSource.Token, TaskCreationOptions.None, app.Scheduler);
}
Tal vez alguien tiene una mejor idea?