Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cooperative multitasking using TPL

We are porting modeling application, which uses IronPython 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:

  1. Tasks queue
  2. each Task from this queue executes one IronPython script
  3. 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:

  1. We want to make infinite loop, which will iterate through Tasks queue
  2. when we get one Task we try to execute it
  3. In PythonScript we want to call C# method and transfer this script to waiting state. but not remove it from the queue.
  4. 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.
  5. In each moment we should have only one active Task
  6. 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?

like image 542
Jevgenij Nekrasov Avatar asked Oct 13 '10 08:10

Jevgenij Nekrasov


1 Answers

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

like image 168
Brent Miller Avatar answered Oct 05 '22 11:10

Brent Miller