Yes ce sont mes classes et elles sont disposables.
Donc quand je parle de Close(), c'est une fonction à moi qui mets le périphérique en standby/ferme la connexion/pousse des trucs dans des fichiers/...
Yes ce sont mes classes et elles sont disposables.
Donc quand je parle de Close(), c'est une fonction à moi qui mets le périphérique en standby/ferme la connexion/pousse des trucs dans des fichiers/...
Bizarre que tu n'arrives pas à mettre tout ça dans le Dispose : vu que c'est une classe perso, ça ne fait ni plus ni moins que ce tu lui dis de faire.
Le Dispose() est bien appelé explicitement (ou via un using) ?
J'pense que Foudge t'a donné la bonne marche à suivre. Implémente IDisposable dans tes classes (qui feront ton Close et nettoyage divers), et utilise les derrière des using. Tu instancie tes objets juste avant, et tu les laisses mourir (se rendrent dispo au GC) après.
Ben il est appelé par le finalizer...
En appelant explicitement, ça semble marcher (sauf que j'ai un truc super bizarre derrière... J'essaie de Dispose une Task... Et il m'insulte qu'il ne peut le faire que si elle est dans divers états... Dont celui dans lequel elle est. ). Je regarderais en détails demain.
En fait, mon code de fin explose (mais n'est pas catchable), et arrête le Dispose() (visiblement une propagation d'exception). (Quand pas appelé pas le Finalizer donc, mais je voudrais bien que ça marche dans ce cas aussi...)
Tu appelle du code C++ pour que ça ne soit pas catchable ?
A tu essayé de canceller ta Task avant de la disposer ? (puis pourquoi disposer ta Task d'ailleurs ? cf Stephen Toub)
Sinon il va ptet falloir nous montrer un bout de code, ça sera sans doutes plus simple pour t'aider.
Nan, dans le cas présent, c'est un tout petit programme sans rien d'exotique.
C'est justement ce que j'essaie de faire (enfin, de la terminer).A tu essayé de canceller ta Task avant de la disposer ?
(Et là, elle était RanToCompletion quand je me suis fait insulter).
(A noter aussi que j'utilise pas de CancellationToken (ça m'avait l'air un poil compliqué à mettre en place), mais un AutoResetEvent (mais ça marche bien en temps normal)... Là je sens qu'on va me répondre que le CancellationToken permet de faire ce que je cherche à faire depuis le début... J'avoue que j'ai pas re-regardé).
Euh... Ou l'analyse de code me le demandait, ou excès de zèle.(puis pourquoi disposer ta Task d'ailleurs ? cf Stephen Toub)
Yes, vais faire ça demain.Sinon il va ptet falloir nous montrer un bout de code, ça sera sans doutes plus simple pour t'aider.
C'est pas compliqué le CancellationToken, faut juste prendre le temps de poser les choses.
Mais oui, comme tu t'en doutais, c'est par là qu'il faut passer.
On attends ton sample alors.
On ne se moque pas de mes conventions de nommage.Code:public class Logger : IDisposable { public bool Ready { get { return PrivateReady; } } private bool PrivateReady = false; private object LockListEventLog = new object(); private List<EventLogContent> ListEvent; private Task Worker; public AutoResetEvent CancelWorker; private string RootFolderPath = ""; public Logger() { LockListEventLog = new object(); RootFolderPath = Manipulator.GetApplicationPath() + @"\Logs"; ListEvent = new List<EventLogContent>(); Run(); } ~Logger() { Dispose(false); } public void Dispose() { Dispose(true); } private void Dispose(bool disposing) { if (!this.Disposed) { Disposed = true; if (Worker != null) { if (Worker.Status == TaskStatus.Running) { try { Stop(); } catch { } } } if (disposing) { if (Worker != null) { Worker.Dispose(); } if (CancelWorker != null) { CancelWorker.Dispose(); } } } } private void WorkingLoop() { Stopwatch PushToFile = new Stopwatch(); bool FileIsOpen = false; int EventCount = 0; lock (LockListEventLog) { ListEvent.Add(new EventLogContent("Info", "Starting session")); } PrivateReady = true; try { while (!CancelWorker.WaitOne(30)) { if (FileIsOpen) { if (!CheckFileDate()) { FileIsOpen = false; } } lock (LockListEventLog) { EventCount = ListEvent.Count; } if (!FileIsOpen && (EventCount > 0)) { FileIsOpen = OpenFile(); if (FileIsOpen) { PushToFile.Restart(); } } if (FileIsOpen) { lock (LockListEventLog) { if (ListEvent.Count > 0) { WriteEvent(ListEvent[0]); ListEvent.RemoveAt(0); } } if (FileIsOpen && (PushToFile.Elapsed.TotalMilliseconds > 4000)) { CloseFile(); FileIsOpen = false; PushToFile.Stop(); } } } } catch (Exception Ex) { //catch rien... } PrivateReady = false; //On vite les listes try { ListEvent.Add(new EventLogContent("Info", "Closing session")); if (ListEvent.Count > 0) { if (!FileIsOpen) { FileIsOpen = OpenFile(); } while (ListEvent.Count > 0) { WriteEvent(ListEvent[0]); ListEvent.RemoveAt(0); } } } catch { } //On ferme le fichier if (FileIsOpen) { CloseFile(); FileIsOpen = false; } } private void Run() { CancelWorker = new AutoResetEvent(false); Worker = new Task(WorkingLoop); Worker.Start(); } public void Stop() { CancelWorker.Set(); try { Worker.Wait(5000); } catch (Exception Ex) { //Rien qui catch... } } }
(Il y a des trucs pas forcément logiques, mais c'est parce que la structure est récupérée d'un autre programme où je log pas mal de trucs différents).
Donc en gros :
- Si j'appelle Stop() ou Set() l'event (ils sont en public juste pour les tests), pendant le fonctionnement du programme, ça marche.
- Si j'appelle Dispose explicitement, ça marche (et ça ne crash plus après, pas comme hier )
- Si Dispose() est appelé par le finalizer, ça plante pendant Worker.Wait(5000) ("PrivateReady = false;" n'est jamais exécutée dans la tâche). Je suppose que les objets commencent à être supprimés à ce moment là puisque je vois la consommation mémoire chuter en même temps.
Chose marrante, hier j'ai laissé le Dispose() sur un point d'arrêt pendant un moment (téléphone)... Quand je l'ai relancé, c'est la seule fois où c'est passé.
C'est à la fermeture du programme, sans appel explicite au Dispose() que t'as un crash ?
Vérifie si tu attrape toutes les "Common Language Runtime Exceptions" (ça doit être coché avec un "check") dans les paramètres de ton débogueur (Ctrl+ D, E), et regarde si en debug il ne te montre par où ça coince.
Puis oui, donne nous plus de détails quand ça explose : quand tu ferme l'appli, ou quand tu passe à null un de ces objets (+ le temps que le GC passe) ?
C’est parce que tu nommes tes données membres privées et tes variables comme des méthodes, du coup il est tout perdu
Si c'est uniquement lors de la fermeture de ton programme, tu est p-e en train de débugger un artefact de débugger. Comment est tu sûr que c'est un crash et pas juste la fermeture de l'application ? Si tout se ferme correctement (pas de processus zombie, etc) quel est ton soucis ?
Dernière modification par Dross ; 18/12/2015 à 17h36.
J'avais justement testé ton code hier soir (avec quelques retouches) et c'est le seul cas où j'ai pu observer ta problématique. J'ai l'impression que le GC n'a pas le temps de terminer son travaille car le processus se termine. Maintenant, je ne connais pas assez la procédure de garbage collecting en .Net, c'est donc p'tet une grosse connerie ce que je raconte.
Mais j'ai trouvé une solution simple : appeler le Dispose à la fermeture du logiciel (dans le Closing ou le Closed par ex), ça te permettra de faire le travail de nettoyage jusqu'au bout, juste avant que l'application se termine. Par contre si ton instance a une durée de vie courte, utilise un using, c'est fait pour.
Ouais mais du coup pour terminer mes trucs correctement je dois penser à appeler Dispose(), or l'idée c'était de ne plus avoir à penser à appeler Close()/Stop()/...
Bon, je vais continuer comme ça du coup, merci pour le coup de main.
On répète tous en chœur : "le garbage collecting c'est pour récupérer de la mémoire, pas pour gérer des lifetimes".
Sleeping all day, sitting up all night
Poncing fags that's all right
We're on the dole and we're proud of it
We're ready for 5 More Years
Tramb à raison, si tu doit finir un processus avant de fermer une application, fait en sorte d'attendre la fin du processus et ne laisse l'application se fermer qu'après. Et ne laisse surtout pas le GC ou autre chose le faire pour toi, sinon tu va avoir des comportements aléatoires comme tu a pus le voir.
C'est à toi de définir clairement le comportement de ton app, donc fait un Task.WaitAll() ou autre mécanisme/choix d'architecture.
Mais après je passe pour un fasciste de merde.
(Alors que je suis un vrai démocrate)
Sleeping all day, sitting up all night
Poncing fags that's all right
We're on the dole and we're proud of it
We're ready for 5 More Years
J'ai une petite question en c++... Bon j'ai un peu honte vu que ça concerne un type de base, mais là je m'arrache les cheveux.
J'utilise la lib libtcod qui est un ensemble d'outils pour développer des roguelikes textuels. Bref, mon projet grossi et depuis le départ, je n'arrive pas à afficher de caractères accentués. La lib se base sur un fichier image contenant les caractères :
Mais lors de l'utilisation des fonctions d'écriture de la lib, je n'ai que des caractères "bizarres" à la place des "é". Ca doit être un problème d'encodage mais il est possible de remapper chaque caractère avec cette méthode :
En gros j'affecte le code ASCII 130 au caractère de la 9ème ligne et 14ème colonne.Code:TCODConsole::root->mapAsciiCodeToFont(130, 9, 14);
Ce qui est cool c'est que j'arrive à afficher un "é" de cette façon :
Le 0, 2 c'est juste la position dans la console.Code:char str = (char)130; console_->print(0, 2, "%c", str);
J'avoue que c'est un peu lourdingue de remapper toutes les lettres accentuées mais il n'y en a pas tant que ça et ça me permettra de continuer en FR.
Le problème c'est que tout ce que j'essai d'autre ne fonctionne pas. un const char* = "é" ne m'affiche pas mon "é".
Au passage la méthode demande un const char* pas de string. J'utilise toutefois uniquement des strings avec la fonction c_str().
C'est un peu confus, mais comment utiliser ce code ascii dans un string ou un const char* qui soit bien interprété par la lib ??? Le top serait que je fasse une fonction à qui je passe mon texte "testé" et qui me la traduit pour qu'il soit comprit par la lib.
Ca commence à faire des noeuds là :/
Rah yes ! C'était vraiment con enfait
J'ai lu sur le forum qu'il utilise cet encodage : https://fr.wikipedia.org/wiki/Page_de_code_850
Du coup j'ai enregistré mes sources dans cet encodage et ça fonctionne.
Merci bien Møgluglu !
Yop les canards, et bonne année au passage.
Je m'adresse plus spécialement aux types en noirs, mais tout le monde peut jouer: est-ce que vous avez des configs de bourrin, genre bi-CPU, gros Xeons, CPU overclockés, mémoires tournant à plus de 2 Ghz?
Je ne vais pas vous demander de me faire des calculs, mais j'aimerais savoir ce que vous avez comme gros mastodontes, et ce qu'on peut faire surtout. Je me suis mis dans l'idée qu'on ne pouvait pas trop clocker des configs Xéon, mais je n'attends que de me faire remettre les idées à l'endroit
Dernière modification par vectra ; 04/01/2016 à 21h19.
Ca compte pas, mais j'ai trouvé cette vidéo hier, sur l'intra-planète: 7 PC en uns.
une balle, un imp (Newstuff #491, Edge, Duke it out in Doom, John Romero, DoomeD again)
Canard zizique : q 4, c, d, c, g, n , t-s, l, d, s, r, t, d, s, c, jv, c, g, b, p, b, m, c, 8 b, a, a-g, b, BOF, BOJV, c, c, c, c, e, e 80, e b, é, e, f, f, f, h r, i, J, j, m-u, m, m s, n, o, p, p-r, p, r, r r, r, r p, s, s d, t, t
Canard lecture
En Python, le type bytes est un format de chaînes sans encodage, la méthode decode retourne une chaîne encodée. Ça permet de manipuler un flux d’octets.
En C++, je ne sais pas, je ne sais même pas comment coder un tri à bulles en C++.
une balle, un imp (Newstuff #491, Edge, Duke it out in Doom, John Romero, DoomeD again)
Canard zizique : q 4, c, d, c, g, n , t-s, l, d, s, r, t, d, s, c, jv, c, g, b, p, b, m, c, 8 b, a, a-g, b, BOF, BOJV, c, c, c, c, e, e 80, e b, é, e, f, f, f, h r, i, J, j, m-u, m, m s, n, o, p, p-r, p, r, r r, r, r p, s, s d, t, t
Canard lecture