2010-10-13 16 views
7

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

  1. Task s cola
  2. cada Task desde esta cola ejecuta un script IronPython
  3. 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:

  1. queremos hacer bucle infinito, que iterar a través de Task s cola
  2. cuando tenemos una Task tratamos de ejecutarlo
  3. En PythonScript queremos llamar a C Método # y transferir este script a estado de espera. pero no eliminarlo de la cola.
  4. En la siguiente iteración cuando obtenemos otra Task, comprobamos que está en estado de espera. si es así, lo despertamos e intentamos ejecutarlo.
  5. En cada momento en que debe tener un solo activo Task
  6. 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?

Respuesta

1

Parece que estaría bien servido para usar el patrón productor/consumidor .NET 4 se ha incorporado a algunas colecciones.

Echa un vistazo a la página 55 en este PDF gratis de Microsoft, Patterns of Parallel Programming