Совместная многозадачность с использованием TPL

Мы переносим приложение моделирования, которое использует скрипты IronPython для настраиваемых действий в процессе моделирования. Существующее приложение выполняет каждый скрипт Python в отдельном потоке и использует для этого кооперативную модель. Теперь мы хотим перенести его на TPL, но сначала мы хотим измерить переключение контекста. . По сути, то, что у нас есть прямо сейчас:

  1. Task s queue
  2. каждая Task из этой очереди выполняет один скрипт IronPython
  3. Внутри скрипта IronPython мы вызываем метод класса C #, который является точка синхронизации и должна перевести Задачу (выполнение IronPython) в состояние ожидания

Что мы хотим сделать:

  1. Мы хотим создать бесконечный цикл, который будет повторяться через Задачу s queue
  2. , когда мы получаем одну Task , мы пытаемся выполнить ее
  3. В PythonScript мы хотим вызвать метод C # и перевести этот скрипт в состояние ожидания. но не удалять его из очереди.
  4. На следующей итерации, когда мы получаем другую Задачу , мы проверяем, находится ли она в состоянии ожидания. если это так, мы разбудим его и попробуем выполнить. Мы думаем о кастомном 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();
            }
       }
    

    Custom Task Scheduler, у него есть один _thread для Task Execution и поле _currentTask для запущенной задачи, также у него есть SleepCurrentTask в этом методе. Я хочу приостановить выполнение текущей задачи, но я не знаю как.

    Клиентский код прост :

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

    Может быть, у кого-то есть идеи получше?

7
задан Jevgenij Nekrasov 20 October 2010 в 10:46
поделиться