IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Occurence d'exception IO innatendue


Sujet :

C#

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut Occurence d'exception IO innatendue
    Hello, L'exception est réellement inattendu dans ce cadre la, surtout qu'elle ne surgit qu'une 1 Fois sur / 3

    Voila le code ou sa planque (code remanier un peu pour tester W_w)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
              try
               {
                   StreamReader readP1 = new StreamReader(Application.StartupPath + "\\pdata\\patchlist.php");
                   readP1.Close();
                }
               catch { Thread.Sleep(400); StreamReader readP2 = new StreamReader(Application.StartupPath + @"\pdata\patchlist.php"); readP2.Close(); }
    quand a ce fameux patchlist, il provient d'un téléchargement aussi robuste que possible :

    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
            public void Download(Uri url, string path, string status)
            {
                Program.myform.statusLabel.Invoke((ThreadStart)delegate()
              {
                  Program.myform.statusLabel.Text = "Status :" + status;
    
              });
                if (!Directory.Exists(Path.GetDirectoryName(path))) Directory.CreateDirectory(Path.GetDirectoryName(path));
                if (File.Exists(path)) File.Delete(path);
                WebClient client = new WebClient();
                client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
                client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
                DataTreatement.wait = true;
                using (WebClient wcDl = new WebClient())
                {
                    try
                    {
                        wcDl.DownloadFileAsync(url, path);
                    }
                    catch { System.Windows.Forms.MessageBox.Show("EXCEPTION TEST"); }
                }
            }

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Points : 1 521
    Points
    1 521
    Par défaut
    StreamReader est IDisposable, il devrait être utilisé dans un using. De plus, si il y a bien un try ... catch sur readP1, il n'y en a pas sur readP2 ce qui signifie que si une exception se produit sur readP2, le programme plante. Ce qui aurait pu nous aider, c'est le message de l'IOException (ou alors il faut le deviner ?). Mais bien entendu, tu ne l'as pas parce que tu utilises un try ... catch qui ne te permet pas de remonter l'erreur. Ton code va effectivement catcher toutes les exceptions (quasiment ...) mais ne sachant pas déterminer quel type d'exception s'est produit, il ne pourra pas entreprendre les actions adéquates.

    Un code robuste serait d'utiliser des constructions du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    try {
       using(StreamReader readP1 = new StreamReader(fileName)) {
          ...
       }
    } catch(IOException ioe) {
       MessageBox.Show("Erreur IOException : " + ioe.Message);
    } catch(Exception e) {
       MessageBox.Show("Erreur Exception : " + e.Message);
    }
    parce qu'on sait que la plupart du temps StreamReader va faire des IOException, mais ce n'est pas toujours le cas (il peut également levé des SecurityException par exemple). De plus ce code permet d'obtenir l'information Message (et d'autres comme StackTrace par exemple) qui permettent de facilement débuguer le code.

    Concernant le code "robuste" (), il sert à quoi le WebClient client ? Il n'est pas utilisé ... et tu instancies un nouveau WebClient (wcDl) pour downloader la page de façon asynchrone pour lequel tu n'es pas abonné aux événements ... je ne comprends pas trop la logique dans tout ça. Même remarque pour ton try ... catch qui est loin d'être "robuste" ... comme la plupart du code que tu as posté ici depuis le début (désolé).

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    non non c'était bon et simple au début, mais j'ai tendance a bidouiller mon code après ce genre d'erreur pour tester ;(.

    Sinon ,l'exception est qu'il ne parvient pas a lire le fichier car il est censé etre déja ouvert W.W

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Points : 1 521
    Points
    1 521
    Par défaut
    ... et donc ? ... la seule raison pour qu'un fichier soit déjà ouvert, c'est qu'il soit déjà ouvert.

    A toi de trouver pourquoi, le code fourni ne nous permet pas, à mon avis, de le savoir.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    Citation Envoyé par Kaidan Voir le message
    ... et donc ? ... la seule raison pour qu'un fichier soit déjà ouvert, c'est qu'il soit déjà ouvert.

    A toi de trouver pourquoi, le code fourni ne nous permet pas, à mon avis, de le savoir.
    Pourtant ca représente 100% de mon code en dehors de la forme.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Points : 1 521
    Points
    1 521
    Par défaut
    Je suppose donc que tu n'attends pas la fin du download pour tenter de charger le fichier.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    Citation Envoyé par Kaidan Voir le message
    Je suppose donc que tu n'attends pas la fin du download pour tenter de charger le fichier.
    le téléchargement étant obligatoirement asynchrone, comment puis-je attendre?

  8. #8
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Points : 1 521
    Points
    1 521
    Par défaut
    En mettant le code dans l'événement qui est lancé lorsque le download est terminé.

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    Citation Envoyé par Kaidan Voir le message
    En mettant le code dans l'événement qui est lancé lorsque le download est terminé.
    dans ce cas je devrais tapez le meme code plus de 4 Fois
    ce dont j'ai besoin c'est d'une sorte de system de queue

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Points : 1 521
    Points
    1 521
    Par défaut
    Heureusement que les gestionnaires d'événements ont un paramètre sender qui permet de retrouver l'objet ayant déclenché l'événement ...

  11. #11
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par F.Saad Voir le message
    dans ce cas je devrais tapez le meme code plus de 4 Fois
    Avec le code de l'exemple je ne vois pas trop comment, mais à ce moment repense l'organisation du système car tu t'y prends probablement mal quelque part

    Citation Envoyé par F.Saad Voir le message
    ce dont j'ai besoin c'est d'une sorte de system de queue
    L'événement qui se déclenche une fois le fichier téléchargé est très bien. Je ne vois pas ce qui te gène (en tout cas pas avec les informations que l'on a pour le moment).

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    Bon, j'ai fais pas mal de recherche mais j'arrive pas a faire ce truc qui a l'air quand meme assez simple.

    Aujourd'hui j'ai découvert la class : ManualResetEvent qui fait ce que je veut.
    Seulement je viens de découvrire qu'enfaite, DownloadASYNC N'est qu'une arnaque car elle n'a pas son propre thread en réalité !

    voila mon code
    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
            public static void Download(string url, string path, string Status)
            {
     
     
                if (!Directory.Exists(Path.GetDirectoryName(path))) Directory.CreateDirectory(Path.GetDirectoryName(path));
                if (File.Exists(path)) File.Delete(path);
                Program.myform.statusLabel.Text = "Status : " + Status;
                System.Uri uri = new Uri(url);
                System.Net.WebClient client = new System.Net.WebClient();
                client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
                client.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
                ma.Reset();
                client.DownloadFileAsync(uri, path);
                ma.WaitOne();
     
     
            }
     
            static void client_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
            {
                if (Program.myform.progressBar1.InvokeRequired)
                {
                    Program.myform.progressBar1.Invoke((ThreadStart)delegate()
                    {
                        Program.myform.progressBar1.Value = e.ProgressPercentage;
                    });
                }
                else
                    Program.myform.progressBar1.Value = e.ProgressPercentage;
            }
     
            static void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
            {
                ma.Set();
                if (!Program.myform.statusLabel.InvokeRequired)
                    Program.myform.statusLabel.Text = "Status : Download Completed";
                else
                {
                    Program.myform.statusLabel.Invoke((ThreadStart)delegate()
                    {
                        Program.myform.statusLabel.Text = "Status : Download Completed";
     
                    });
                }
    Voyez comme j'ai mis le WaitOne juste aprés que mon téléchargement commence.
    Avec mes anciennes données : " LE DL ASYNC se fait sur un autre thread"
    sur papier, le telechargement etait suposé se faire tranquillement pendant que le Wait One se chargerais d'attendre pour moi qu'il soit fini, Cela en recevant un signal de la part du OnCompleted Event.

    Seulement, comme je vous l'ai dit, le DL ASYNC est une vrai arnaque, et le WaitOne a pour conséquence de la stopper aussi.
    Résultat : mon fichier reste a 0kb sur le HDD, les events ne commence jamais et moi je suis encore bloqué !!

  13. #13
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Il y a autre chose qui doit bloquer car DownloadFileAsync est bien asynchrone, comme indiqué sur la MSDN.
    Citation Envoyé par MSDN
    Télécharge, vers un fichier local, la ressource ayant l'URI spécifié. Cette méthode ne bloque pas le thread appelant.
    ou encore
    Citation Envoyé par MSDN
    Le fichier est téléchargé de manière asynchrone à l'aide de ressources de thread automatiquement allouées à partir du pool de threads.
    En regardant rapidement avec Reflector on voit que c'est bien le cas, si on mettait en doute la MSDN.

    Un exemple tout simple qui chez moi fonctionne parfaitement
    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
    using System;
    using System.Net;
    using System.Threading;
     
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                ManualResetEvent resetEvent = new ManualResetEvent(false);
     
                using (WebClient client = new WebClient())
                {
                    client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(ClientDownloadFileCompleted);
                    client.DownloadFileAsync(
                        new Uri(@"http://www.developpez.com/template/images/logo.gif"), 
                        @"C:\logoDVP.gif", 
                        resetEvent);
                }
     
                Console.WriteLine("DL en cours ...");
     
                resetEvent.WaitOne();
     
                Console.WriteLine("DL fini");
     
                Console.ReadLine();    
            }
     
            static void ClientDownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
            {            
                ((ManualResetEvent)e.UserState).Set();
            }
        }
    }
    Au passage, évite de faire l'invoke sur le thread UI comme tu le fais actuellement (d'ailleurs je ne comprends pas le pourquoi du ThreadStart à ce niveau). Tu doubles le code et donc le risque d'erreur si tu modifies une partie mais pas l'autre. Il vaut mieux faire quelque chose comme ceci par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private delegate void InvokeMethodCallback(MethodInvoker methodInvoker);
    private void InvokeMethod(MethodInvoker mi)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new InvokeMethodCallback(InvokeAction), methodInvoker);
        }
        else
        {
            methodInvoker();
        }
    }
    Et à l'utilisation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InvokeAction(delegate { /* Le traitement à déléguer au thread UI */ });

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 192
    Points : 160
    Points
    160
    Par défaut
    Merci ca a marcher, mais ca bloquer mon UI, donc pas intéressant.
    J'ai réparer le programme en utilisant un tableau de Queue.

  15. #15
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par F.Saad Voir le message
    Merci ca a marcher, mais ca bloquer mon UI
    Un peu normal dans le cadre de l'exemple, c'est le principe même du ResetEvent.

    Sinon je ne vois toujours pas trop l'intérêt d'utiliser une Queue. Si tu lances plusieurs téléchargements (car je suppose que c'est le but si tu parles de Queue) avec DownloadFileAsync, tu auras autant d'événements déclenchés à chaque étape (progression, fin du téléchargement, ...).

    Tout ce que tu as besoin c'est d'avoir la liste des fichiers que tu veux télécharger en leur collant un guid (ou même le nom s'il est unique par exemple) et de passer cet identifiant dans le UserState lors de l'appel à DownloadFileAsync. Tu pourras accéder à cette info dans les événements ensuite, ce qui te permet de savoir à quel fichier cela correspond.

    Le UserState pourrait même être un objet métier au besoin. Que l'on pourrait, j'en suis certain, binder : on implémente INotifyPropertyChanged sur la classe métier et on met à jour les infos de l'objet sur les événements (progression, téléchargement fini). Il suffit ensuite de gérer une liste de ces objets qui servirait de DataSource à un contrôle qui afficherait la progression des téléchargements (comme dans FireFox par exemple).

    Enfin bon, si au final le problème est réglé pense à cliquer sur

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [debutant] "exception occured executing command line"
    Par hariri dans le forum Eclipse Java
    Réponses: 13
    Dernier message: 22/05/2007, 10h06
  2. Réponses: 2
    Dernier message: 16/11/2006, 17h09
  3. Réponses: 2
    Dernier message: 27/09/2005, 16h32
  4. [Graphics2D]pb, fatal exception occured
    Par julien.v dans le forum 2D
    Réponses: 17
    Dernier message: 03/06/2005, 11h09
  5. Error 80020009. Exception occurred
    Par twizell dans le forum ASP
    Réponses: 5
    Dernier message: 14/04/2005, 20h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo