2010-10-13 64 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