Salut,
pas besoin de faire attendre un thread (c'est une idée fixe ! =) ). Dans le callback de ton event, tu fais partir ton operation en asynchrone (Pool, Thread nommé, ce que tu veux) et c'est tout. =)
J'aurais pas dit mieux.
J'ajoute que les event étant fondamentalement monothread, c'est à la fonction abonnée, qui sera forcément lancée dans le même thread que celui qui a modifié la liste, de commencer un traitement dans un nouveau thread.
Par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 bindingList.ListChanged += UneFonction; private void UneFonction(object sender, JeSaisPlusQuelDérivédEventArgs e) { // ici, on est dans le même thread que le déclenchement de l'event unthread.BeginInvoke(...); // et là tu multithreade comme un ouf ! :p }
ಠ_ಠ
Justement, je veux faire attendre mon thread car ce thread doit utiliser les données qui vont arriver dans la Queue ou la BindingList.
Même si l'event déclenche une fonction, il faudrait que le thread attende que la fonction se déclenche.
J'espère que vous comprenez ce que je veux faire. Merci d'avance pour votre aide.
A vrai dire, non pas vraiment. =)
En gros, tu veux que chaque fois que ta liste (ou autre collection) change, tu puisses faire un traitement asynchrone sur ce changement. Si oui, est ce que ce traitement doit imperativement etre fait par le meme thread ou bien on peut faire ca en parallele ?
Un code comme ca, par exemple, ne conviendrait pas ?
D'une maniere general, un thread en attente, ca ne se justifie pas souvent (Winform a part c'est particulier). Les avantages que t'offre le pool en terme de perf (sans commune mesure avec la creation d'un thread, si c'est ca ton soucis), et de confort d'utilisation ont vraiment rendu le multithreading plus simple.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 class Program { static void Main(string[] args) { MaCollection<string> coll = new MaCollection<string>(); coll.ItemAdded += new EventHandler<MaCollectionEventArgs<string>>(coll_ItemAdded); coll.Add("Titi"); coll.Add("Toto"); coll.Add("Tutu"); Console.Read(); } static void coll_ItemAdded(object sender, MaCollectionEventArgs<string> e) { ThreadPool.QueueUserWorkItem( new WaitCallback( delegate { //On force la capture de la donnée, et on peut l'utiliser dans le thread string s = e.Data; Trace.WriteLine("Le traitement commence"); Thread.Sleep(1000); Trace.WriteLine("Le traitement est fini. Data : " + s); })); } } class MaCollectionEventArgs<T> : EventArgs { public MaCollectionEventArgs(T data) { m_data = data; } T m_data; public T Data { get { return m_data;} } } class MaCollection<T> : Collection<T> { public event EventHandler<MaCollectionEventArgs<T>> ItemAdded; protected override void InsertItem(int index, T item) { if (ItemAdded != null) ItemAdded(this, new MaCollectionEventArgs<T>(item)); base.InsertItem(index, item); } }
Vu comme je vois les choses, ce traitement doit être fait par le même thread et donc ton exemple ne me conviendrait pas.
En fait, mon programme est une DLL qui agit en tant que serveur. Elle recoit des requêtes d'autres applications et doit les envoyer à un automate programmable. La réponse doit ensuite être traitée avant d'être renvoyée à l'application qui a envoyé la requête.
Au départ j'ai pensé à utiliser un threadpool (chaque requête traitée par un thread) mais j'ai vu que c'était compliqué de mettre des valeurs de retour. Alors j'ai programmé une Queue qui stocke les requêtes en attendant qu'un thread vienne chercher les données pour les envoyer à l'automate. Ensuite les réponses qui viennent de l'automate sont stockées dans une autre Queue et lues par la fonction "principale" de la DLL (celle qui est appelée par les applications extérieures).
C'est pourquoi je voulais que le thread fasse un Wait en attendant les requêtes, et ensuite que la fonction principale fasse également un wait en attendant la réponse (qui peut arriver en plusieurs morceaux)
Voilà, j'espère que vous voyez mieux mon problème. Merci d'avance pour votre aide.
Salut Levalp,
peut etre peut-on utiliser les differents schemas d'invocation de methodes asynchrones, au lieu de thread en wait et de queue. Comme ceci :
Le principe etant d'avoir un manager (ici static, mais qu'importe) qui connait le truc à interroger. On l'utilise en appelant la methode EnqueueNewJob, en bloquant sur le handle retourné, et enfin en rapatriant les resultats une fois l'event signalé. D'ailleurs on pourrait se passer du WaitHandle, EndInvoke etant bloquant en lui meme. Le manager n'est jamais bloqué (et donc reste utilisable).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 delegate DataClass DataClassDelegate(string request); class Program { static void Main(string[] args) { WaitHandle waiter = Manager.EnqueueNewJob("Ma requete"); waiter.WaitOne(); DataClass result = Manager.GetResult("Ma requete"); } } class Manager { static Dictionary<string, IAsyncResult> dic = new Dictionary<string,IAsyncResult>(); static Serveur serv = new Serveur(); static DataClassDelegate del = new DataClassDelegate(serv.Compute); public static WaitHandle EnqueueNewJob(string request) { IAsyncResult result = del.BeginInvoke(request, null, null); dic.Add(request, result); return result.AsyncWaitHandle; } public static DataClass GetResult(string p) { DataClassDelegate del = (dic[p] as AsyncResult).AsyncDelegate as DataClassDelegate; return del.EndInvoke(dic[p]); } } /// <summary> /// classe fournissant les resultats /// expose une methode DataClass Compute(string) de traitement des requetes /// </summary> class Serveur { static object s_syncO = new object(); public DataClass Compute(string request) { lock (s_syncO) { //On simule un traitement Thread.Sleep(1000); DataClass data = new DataClass(request); data.Result = "resultat de " + data.Request; return data; } } } /// <summary> /// Class encapsulant une requete et son resultat /// </summary> class DataClass { string m_request; public string Request { get { return m_request; } } public string Result { get; set; } public DataClass(string request) { m_request = request; } }
Bon ici, ce n'est qu'une decoration au principe de methode asynchrone, mais je pense que ca devrait plus ou moins correspondre à tes attentes.
En esperant que ca t'aide un peu. Bon courage.
edit : Un oubli, il faut, bien sur, penser a enlever les references du dictionary une fois traitées.
salut
Si tu veux que ton thread soit endormi en attendant qu'un traitement se soit
fini, tu peux utiliser par exemple les Mutex ou la synchronisation d'objet
Ton thread va faire un Wait()...
Et dans l'event branché sur le OnChange de ta bindinglist, tu vas faire un
simple Pulse() de l'objet de synchronisation..
En faisant ainsi, tu evites que ton thread en attente fasse du pooling.. tu
évites qu'un autre thread réalise le traitement sur le changement attendu...
Par contre, si cela va fonctionner, je ne trouve pas cela très propre.. mais parfois, certaines situations sont malheureusement plus facile à appréhender
de cette façon là...
The Monz, Toulouse
The Monz, Toulouse
Expertise dans la logistique et le développement pour
plateforme .Net (Windows, Windows CE, Android)
OK. C'est quand même assez compliqué.
Je repose quand même la question : existe-t-il une fonction wait qui permette à un thread d'attendre le déclenchement d'un événement ?
Merci d'avance.
Même réponse : un event n'a rien à voir avec les threads. C'est la fonction abonnée à un événement qui doit lancer un traitement dans un thread donné, pas ce thread donné qui doit attendre un event.
ಠ_ಠ
Je ne comprends pas comment la fonction abonnée va lancer le traitement dans le thread. Le thread dans lequel le traitement va être lancé peut-il faire un wait en attendant que la fonction abonnée lance le traitement ?
J'ai regardé la fonction WaitForSingleObject de la librairie kernel32.dll, mais je ne comprend pas trop bien comment elle fonctionne. Penses-tu qu'elle soit utilisable dans ce cas là ?
Mais pourquoi veux tu à tout prix avoir quelque chose en attente ?????
Un event externe se produit, on déclenche la fonction qui doit faire le traitement (dans un thread séparé ou pas, peu importe) et basta.
Pourquoi vouloir à tout prix ces état d'attentes qui ne correspondent a priori à rien ? (à moins que tu ais une raison très concrète et argumentée, dans ce cas merci de la donner).
Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...
Une réponse vous a aidé ? utiliser le bouton
"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
La raison est : ma DLL qui agit en tant que serveur va recevoir des requêtes de l'extérieur, cette DLL contient une fonction qui va envoyer des requêtes à un automate programmable, et il faudra bien que cette fonction attende la réponse. Je pensais faire cela avec un WaitForSingleObject mais s'il y a une meilleure solution je suis preneur !
Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...
Une réponse vous a aidé ? utiliser le bouton
"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
Bon, donc tu envoie ta trame à l'automate, dans le handler de l'event DataReceived du SerialPort, tu procéde à la lecture et tu renvoie la réponse à ton client.
Je ne vois pas trop la necessité d'état d'attente ici.
Tu peux en revanche mettre plusieurs thread si ton automate est susceptible de traiter plusieurs requetes simultanément ou si tu as plusieurs automates.
Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...
Une réponse vous a aidé ? utiliser le bouton
"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
Ok, et en effet le Queue est un bon choix ici.
La, il est possible que les thread multiples aient de l'interêt (à raison d'une thread par automate) mais elle n'ont pas plus de raison d'être mise en attente que ta thread pour automate unique.Plus tard je suis en effet censé pouvoir gérer plusieurs automates simultanément.
Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...
Une réponse vous a aidé ? utiliser le bouton
"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager