2010-10-13 55 views
7

我們正在移植建模應用程序,該應用程序在建模過程中使用IronPython腳本進行自定義操作。現有應用程序在單獨的線程中執行每個Python腳本,併爲此使用協作模型。現在我們要將它移植到TPL,但首先我們要測量上下文切換 。 基本上,我們現在所擁有的:使用TPL的協作式多任務

  1. Task
  2. 每個Task此隊列中執行一個IronPython的腳本
  3. 裏面IronPython的腳本中,我們要求C#類的方法,這是同步點,並應轉移Task(IronPython的執行),以等待狀態

我們想要做什麼:

  1. 我們要無限循環,將通過Task
  2. 迭代,當我們得到一個Task我們嘗試執行
  3. 在PythonScript我們要調用C#方法,並且此腳本轉移到等待狀態。但不能將其從隊列中移除。
  4. 在下一次迭代時,我們得到另一個Task我們檢查它是否處於等待狀態。如果是的話,我們將其喚醒並嘗試執行。
  5. 在每一個時刻,我們應該只有一個活動Task
  6. 最後,我們要衡量我們能獲得多少Task每秒

我真的不知道是什麼事情大約合作多任務執行? 我們正在考慮定製TaskScheduler,這是好的方法嗎?或者有人知道更好的解決方案?

謝謝。

更新時間:

好了,比如,我有這樣的代碼:

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

自定義任務計劃程序,它有一個_thread任務執行和正在運行的任務_currentTask領域,也有SleepCurrentTask在這種方法中,我想暫停當前的任務執行,但我不知道如何執行。

客戶端代碼很簡單:

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


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

也許有人有更好的想法?

回答

1

這聽起來像你會很好地使用生產者/消費者模式.NET 4內置到一些集合。

查看第55頁,來自Microsoft的免費PDF,Patterns of Parallel Programming