J'ai une bibliothèque (prise réseau) code qui fournit une Task
-en fonction de l'API pour l'attente des réponses à des demandes en fonction TaskCompletionSource<T>
. Cependant, il y a une gêne dans le TPL, il semble impossible d'empêcher synchrone continuations. Ce que je voudrais , comme pour être en mesure de faire est soit:
- dire à un
TaskCompletionSource<T>
qui ne devrait pas permettre aux appelants de se joindre avec desTaskContinuationOptions.ExecuteSynchronously
, ou - définir le résultat (
SetResult
/TrySetResult
) d'une manière qui indique queTaskContinuationOptions.ExecuteSynchronously
devraient être ignorées, et l'utilisation de la piscine à la place
Plus précisément, le problème que j'ai est que les données entrantes sont traitées par un lecteur dédié, et si un appelant peut fixer avec TaskContinuationOptions.ExecuteSynchronously
ils peuvent enrayer le lecteur (qui ne touche pas uniquement eux). Auparavant, j'ai travaillé autour de cette quelques hackery qui détecte si toutes les suites sont présents, et si elles le sont, il pousse l'achèvement sur l' ThreadPool
, cependant cela a un impact significatif si l'appelant a saturé leur file d'attente de travail, que la fin ne sera pas obtenir traitées en temps opportun. Si elles sont à l'aide de Task.Wait()
(ou similaire), ils seront alors essentiellement de blocage eux-mêmes. De même, c'est pourquoi le lecteur est sur un thread dédié plutôt que d'utiliser des travailleurs.
Donc, avant j'ai essayer et de nag le TPL de l'équipe: j'ai loupé une option?
Points clés:
- Je ne veux pas que les appelants externes pour être en mesure de pirater mon thread
- Je ne peux pas utiliser l'
ThreadPool
comme une mise en œuvre, comme il doit fonctionner lorsque la piscine est saturé
L'exemple ci-dessous, produit un résultat (la commande peut varier en fonction du moment):
Continuation on: Main thread
Press [return]
Continuation on: Thread pool
Le problème, c'est le fait qu'un hasard de l'appelant a réussi à obtenir une continuation de "fil conducteur". Dans le code réel, ce serait d'interrompre la primaire reader; de mauvaises choses!
Code:
using System;
using System.Threading;
using System.Threading.Tasks;
static class Program
{
static void Identify()
{
var thread = Thread.CurrentThread;
string name = thread.IsThreadPoolThread
? "Thread pool" : thread.Name;
if (string.IsNullOrEmpty(name))
name = "#" + thread.ManagedThreadId;
Console.WriteLine("Continuation on: " + name);
}
static void Main()
{
Thread.CurrentThread.Name = "Main thread";
var source = new TaskCompletionSource<int>();
var task = source.Task;
task.ContinueWith(delegate {
Identify();
});
task.ContinueWith(delegate {
Identify();
}, TaskContinuationOptions.ExecuteSynchronously);
source.TrySetResult(123);
Console.WriteLine("Press [return]");
Console.ReadLine();
}
}