2010-10-13 6 views
7

Przenosimy aplikację modelującą, która wykorzystuje skrypty IronPython do niestandardowych działań w procesie modelowania. Istniejąca aplikacja wykonuje każdy skrypt Pythona w osobnym wątku i wykorzystuje do tego model współpracy. Teraz chcemy przenieść go na TPL, ale najpierw chcemy zmierzyć przełączanie kontekstów: . Zasadniczo, co mamy teraz:Wielozadaniowość kooperacyjna za pomocą TPL

  1. Task s kolejka
  2. każdy Task z tej kolejki wykonuje skrypt jeden IronPython
  3. Wewnątrz skryptu IronPython wzywamy do C# metody klasy, który jest punktem synchronizacji i powinien przenosić Task (IronPython wykonanie) na stanie oczekiwania

co chcemy zrobić:

  1. Chcemy mieć nieskończoną pętlę, która będzie iterację Task s kolejce
  2. gdy mamy jeden Task staramy się go
  3. W PythonScript chcemy zadzwonić C Metoda # i przenieść ten skrypt do czekania stan wykonania. ale nie usuwaj go z kolejki.
  4. W następnej iteracji, gdy otrzymamy kolejny Task sprawdzamy, czy jest w stanie oczekiwania. jeśli tak, obudzimy to i spróbujemy wykonać.
  5. W każdej chwili powinniśmy mieć tylko jedną aktywną Task
  6. I wreszcie chcemy zmierzyć ile Task możemy wykonać za drugim

ja naprawdę nie wiem, czy to coś o wielozadaniowości? Myślimy o niestandardowym TaskScheduler, czy to dobre podejście? A może ktoś zna lepsze rozwiązanie?

Dzięki.

Aktualizacja:

Ok, więc na przykład, mam taki kod:

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

klienta Task Scheduler, to jeden _thread za wykonanie zadań i _currentTask dziedzinie na prowadzenie zadania, również ma SleepCurrentTask w tej metodzie chcę zawiesić bieżące wykonywanie zadań, ale nie wiem jak.

kod klienta jest prosty:

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


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

Może ktoś ma lepsze pomysły?

Odpowiedz

1

Wygląda na to, że dobrze byłoby użyć wzorca producenta/konsumenta. Platforma 4 została wbudowana w kilka kolekcji.

Sprawdź stronę 55 w tym bezpłatnym pliku PDF firmy Microsoft, Patterns of Parallel Programming

Powiązane problemy