2010-10-13 5 views
7

Nous portons une application de modélisation, qui utilise des scripts IronPython pour des actions personnalisées dans le processus de modélisation. L'application existante exécute chaque script Python dans un thread séparé et utilise un modèle coopératif pour cela. Maintenant nous voulons le porter au TPL, mais d'abord nous voulons mesurer le changement de contexte . Fondamentalement, ce que nous avons en ce moment:Multitâche coopératif utilisant TPL

  1. Task de la file d'attente
  2. chaque Task de cette file d'attente exécute un script IronPython
  3. intérieur de script IronPython que nous appelons pour la méthode de la classe C#, qui est le point de synchronisation et devrait transférer Task (exécution IronPython) à l'état d'attente

Ce que nous voulons faire:

  1. Nous voulons faire boucle infinie, qui itérer la file d'attente Task
  2. quand nous obtenons un Task nous essayons de l'exécuter
  3. En PythonScript nous voulons appeler la méthode C# et transférer ce script à l'état d'attente. mais ne pas le retirer de la file d'attente.
  4. Lors de la prochaine itération lorsque nous recevons un autre Task, nous vérifions s'il est en attente. si oui, nous le réveillons et essayons d'exécuter.
  5. Dans chaque instant nous ne devrions avoir qu'un seul actif Task
  6. Et enfin, nous voulons mesurer combien Task nous pourrions exécuter par seconde

Je ne sais pas vraiment est-il quelque chose à multitâche coopératif? Nous pensons à la coutume TaskScheduler, est-ce une bonne approche? Ou quelqu'un connaît-il une meilleure solution?

Merci.

Mise à jour:

Ok, donc par exemple, j'ai un tel code:

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

Planificateur de tâches personnalisée, il a un _thread pour l'exécution des tâches et _currentTask domaine pour la tâche en cours d'exécution, aussi il a SleepCurrentTask Dans cette méthode, je veux suspendre l'exécution de la tâche en cours, mais je ne sais pas comment.

code client est simple:

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


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

Peut-être que quelqu'un a de meilleures idées?

Répondre

1

Il semble que vous seriez bien servi pour utiliser le modèle producteur/consommateur .NET 4 a intégré à quelques collections. Consultez la page 55 dans ce PDF gratuit de Microsoft, Patterns of Parallel Programming