File d'attente des processus multithread ou des tâches
J'ai une téléphonie de l'application message dans lequel il y a beaucoup beaucoup de messages à traiter.Parce que les ports téléphoniques sont limitées, de sorte que le message sera traité en premier en premier. Chaque message a une drapeau "prendre en compte" qui indique quel est traitée. Il a été initialisé comme le faux bien sûr.
Je veux mettre tous les messages dans une file d'attente puis de les traiter avec plusieurs threads ou des tâches.
public class MessageQueue
{
public Queue MessageWorkItem { get; set; }
public Messages Message { get; set; }
public MessageQueue()
{
MessageWorkItem = new Queue();
Message = new Messages();
}
public void GetMessageMetaData()
{
try
{
//It is just a test, add only one item into the queue
Message.MessageID = Guid.NewGuid();
Message.NumberToCall = "1111111111";
Message.FacilityID = "3333";
Message.NumberToDial = "2222222222";
Message.CountryCode = "1";
Message.Acknowledge = false;
}
catch (Exception ex)
{
}
}
public void AddingItemToQueue()
{
GetMessageMetaData();
if (!Message.Acknowledge)
{
lock (MessageWorkItem)
{
MessageWorkItem.Enqueue(Message);
}
}
}
}
public class Messages
{
public Guid MessageID { get; set; }
public string NumberToCall { get; set; }
public string FacilityID { get; set; }
public string NumberToDial { get; set; }
public string CountryCode { get; set; }
public bool Acknowledge { get; set; }
}
Maintenant, ma question est comment faire pour retirer l'élément de la file d'attente avec le multithreading.
Pour chaque élément de la file d'attente, je veux exécuter un script.
public void RunScript(Message item)
{
try
{
PlayMessage(item);
return;
}
catch (HangupException hex)
{
Log.WriteWithId("Caller Hungup!", hex.Message);
}
catch (Exception ex)
{
Log.WriteException(ex, "Unexpected exception: {0}");
}
}
Ce que je pensais, c'était de voir si
si(MessageWorkItem.Count >= 1)
Puis faire quelque chose mais j'ai besoin de code de l'aide.
qui ver de framework que vous utilisez
4 ou .NET 4.5. Selon ce qui est très bien.
OriginalL'auteur | 2014-03-27
Vous devez vous connecter pour publier un commentaire.
Si vous pouvez utiliser .Net 4.5, je vous suggère de regarder Flux de données à partir de la Task Parallel Library (TPL).
Cette page conduit à beaucoup d'exemple soluces comme Comment: mettre en Œuvre un Producteur-Consommateur de Flux de données de Motif et Procédure pas à pas: à l'Aide de Flux de données dans une Application Windows Forms.
Jetez un oeil à la documentation pour voir si elle pourrait vous aider. C'est beaucoup, mais je pense qu'il serait probablement votre meilleure approche.
Sinon, vous pouvez regarder dans l'aide d'une
BlockingCollection
avec sesGetConsumingEnumerable()
méthode d'accès à des éléments dans la file d'attente.Ce que vous faire est de diviser le travail dans les objets que vous souhaitez traiter d'une certaine façon, et d'utiliser une BlockingCollection pour gérer la file d'attente.
Un exemple de code utilisant
ints
plutôt que des objets comme les éléments de travail va aider à le démontrer:Lorsqu'un thread a fini avec l'élément en cours, il permettra d'éliminer un nouvel élément à partir de la file d'attente de travail, processus de cet élément, puis l'ajouter à la file d'attente de sortie.
Séparé thread consommateur supprime complété les éléments de la file d'attente de sortie et fait quelque chose avec eux.
À la fin, on doit attendre que tous les travailleurs à la fin (de la Tâche.WaitAll(travailleurs) a) avant que nous puissions marquer la sortie de la file d'attente est terminée (outputQueue.CompleteAdding()).
Ah, vous avez eu la .Net 4.0 tag sur votre question (si quelqu'un l'a fixé à ce que vous êtes déjà, j'ai remarqué! 🙂
J'ai édité ma réponse légèrement à la lumière des informations ci-dessus.
--@Mattew, pour mon cas particulier, où dois-je placer mon RunScript()? Je suppose que dans le vide travailleur()?
Yep, ce serait l'endroit le plus approprié. La charge utile serait
workItem
, ce qui vous ferait quel que soit le type vous avez besoin pour stocker les informations que vous souhaitez traiter comme une unité de travail - sans doute une instance deMessage
dans votre cas? Dans ce cas, vous pourriez utiliser uneBlockingCollection<Message>
OriginalL'auteur Matthew Watson
En parallèle.ForEach de TPL. C'est en parallèle pour chaque.
De l'échantillon (modifié MessageWorkItem de File d'attente générique):
Vous êtes également l'ajout d'éléments à une file d'attente lors de l'itération sur elle, qui va lever une exception, et aussi être soumis à toutes sortes de conditions de course en raison tot il fait qu'il est encore fait à partir de différents threads.
Queue
n'est tout simplement pas conçu pour être accessible à partir de plusieurs threads simultanément.Vous êtes à 100% de réponses correctes à propos de la "ajout d'éléments à une file d'attente lors de l'itération sur elle", mais une clarification, je veux faire sur votre deuxième déclaration.
Parallel.ForEach
ne sera pas multithread accède à laIEnumerable<T>
à l'aide de l'outil de partitionnement par défaut, il va sortir un tas d'éléments dans une file d'attente interne en utilisant un seul fil à la main que le travail à plusieurs threads de travail. Mais encore une fois je tiens à souligner que Servy est vrai que la lecture de ce thread unique et de l'écriture à l'aide de l'un ou de plusieurs autres threads n'est pas faisable avec de la File d'attente de l'agent recenseur.OriginalL'auteur eXit