2010-10-13 15 views
7

Stiamo eseguendo il porting dell'applicazione di modellazione, che utilizza gli script IronPython per le azioni personalizzate nel processo di modellazione. L'applicazione esistente esegue ciascuno script Python in un thread separato e utilizza il modello cooperativo per questo. Ora vogliamo portarlo su TPL, ma prima vogliamo misurare il cambio di contesto . In sostanza, quello che abbiamo in questo momento:Multitasking cooperativo con TPL

  1. Task s coda
  2. ogni Task da questa coda esegue lo script uno IronPython
  3. All'interno di script IronPython chiediamo C# metodo di classe, che è punto di sincronizzazione e dovrebbe trasferire Task (esecuzione IronPython) per stato di attesa

Quello che vogliamo fare:

  1. vogliamo fare loop infinito, che sarà scorrere Task s coda
  2. quando arriviamo uno Task cerchiamo di eseguirlo
  3. In PythonScript vogliamo chiamare C Metodo # e trasferire questo script per stato di attesa. ma non rimuoverlo dalla coda.
  4. Alla successiva iterazione quando otteniamo un altro Task controlliamo che sia in stato di attesa. se è così, lo svegliamo e proviamo a farlo.
  5. In ogni momento si dovrebbe avere un solo attiva Task
  6. E infine vogliamo misurare quanti Task potremmo eseguire al secondo

Io in realtà non so è qualcosa su multitasking cooperativo? Stiamo pensando all'abitudine TaskScheduler, è un buon approccio? O qualcuno conosce una soluzione migliore?

Grazie.

Aggiornato:

Ok, così per esempio, non ho tale codice:

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(); 
     } 
    } 

personalizzati Utilità di pianificazione, ha una _thread per l'esecuzione delle attività e _currentTask campo per l'esecuzione di compiti, anche ha SleepCurrentTask in questo metodo voglio sospendere l'esecuzione corrente del Task, ma non so come.

Codice cliente è semplice:

CancellationTokenSource tokenSource = new CancellationTokenSource(); 
    Application app = Application.Create(); 


    Task task = Task.Factory.StartNew(() => 
    { 
     app.Scheduler.SleepCurrentTask(); 
    }, 
    tokenSource.Token, TaskCreationOptions.None, app.Scheduler); 
} 

Forse qualcuno ha un'idea migliore?

risposta

1

Sembra che tu possa essere ben servito per utilizzare il pattern produttore/consumatore. NET 4 ha integrato alcune raccolte.

Controlla pagina 55 in questo PDF gratuito da Microsoft, Patterns of Parallel Programming

Problemi correlati