Nous portons une application de modélisation, qui utilise des scripts IronPython pour des actions personnalisées dans le processus de modélisation. L'application existante exécute chaque script Python dans un thread séparé et utilise un modèle coopératif pour cela. Maintenant nous voulons le porter au TPL, mais d'abord nous voulons mesurer le changement de contexte . Fondamentalement, ce que nous avons en ce moment:Multitâche coopératif utilisant TPL
Task
de la file d'attente- chaque
Task
de cette file d'attente exécute un script IronPython - intérieur de script IronPython que nous appelons pour la méthode de la classe C#, qui est le point de synchronisation et devrait transférer
Task
(exécution IronPython) à l'état d'attente
Ce que nous voulons faire:
- Nous voulons faire boucle infinie, qui itérer la file d'attente
Task
- quand nous obtenons un
Task
nous essayons de l'exécuter - En PythonScript nous voulons appeler la méthode C# et transférer ce script à l'état d'attente. mais ne pas le retirer de la file d'attente.
- Lors de la prochaine itération lorsque nous recevons un autre
Task
, nous vérifions s'il est en attente. si oui, nous le réveillons et essayons d'exécuter. - Dans chaque instant nous ne devrions avoir qu'un seul actif
Task
- Et enfin, nous voulons mesurer combien
Task
nous pourrions exécuter par seconde
Je ne sais pas vraiment est-il quelque chose à multitâche coopératif? Nous pensons à la coutume TaskScheduler
, est-ce une bonne approche? Ou quelqu'un connaît-il une meilleure solution?
Merci.
Mise à jour:
Ok, donc par exemple, j'ai un tel 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();
}
}
Planificateur de tâches personnalisée, il a un _thread
pour l'exécution des tâches et _currentTask
domaine pour la tâche en cours d'exécution, aussi il a SleepCurrentTask
Dans cette méthode, je veux suspendre l'exécution de la tâche en cours, mais je ne sais pas comment.
code client est simple:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Application app = Application.Create();
Task task = Task.Factory.StartNew(() =>
{
app.Scheduler.SleepCurrentTask();
},
tokenSource.Token, TaskCreationOptions.None, app.Scheduler);
}
Peut-être que quelqu'un a de meilleures idées?