We are porting modeling application, which uses IronPyt开发者_开发知识库hon scripts for custom actions in modeling process. The existing application executes each Python script in separate thread and uses cooperative model for this. Now we want to port it to TPL, but first we want to measure context switching . Basically, what we have right now:
Task
s queue- each
Task
from this queue executes one IronPython script - Inside IronPython script we call for C# class method, which is synchronization point and should transfer
Task
(IronPython execution) to waiting state
What we want to do:
- We want to make infinite loop, which will iterate through
Task
s queue - when we get one
Task
we try to execute it - In PythonScript we want to call C# method and transfer this script to waiting state. but not remove it from the queue.
- On next iteration when we get another
Task
we check is it in the waiting state. if so we wake it up and try to execute. - In each moment we should have only one active
Task
- And finally we want to measure how many
Task
we could execute per second
I don't really know is it something about cooperative multitasking?
We are thinking about custom TaskScheduler
, is it good approach? Or does someone know better solution?
Thanks.
Updated:
Ok ,so for example, I have such 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();
}
}
Custom Task Scheduler, it has one _thread
for Task execution and _currentTask
field for running task, also it has SleepCurrentTask
in this method I want to suspend current Task execution, but I don't know how.
Client code is simple:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Application app = Application.Create();
Task task = Task.Factory.StartNew(() =>
{
app.Scheduler.SleepCurrentTask();
},
tokenSource.Token, TaskCreationOptions.None, app.Scheduler);
}
Maybe someone has better ideas?
It sounds like you'd be well served to use the producer/consumer pattern .NET 4 has built in to a few collections.
Check out page 55 in this free PDF from Microsoft, Patterns of Parallel Programming
精彩评论