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 :

Synchronisation de processus


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut Synchronisation de processus
    Bonjour,

    J'ai un programme dans lequel je créer un processus. Ce processus est un application console qui va faire des demandes à l'utilisateur. Le truc c'est que je voudrais que ce soit l'application qui y réponde et non l'utilisateur.

    Pour cela il faut utilisé l'entrée et sorties standart et les redirigés. Jusqu'a là pas de problème.

    Le processus va faire un traitement long et après celui-ci faire une demande à l'utilisateur.
    Comment faire depuis mon programme pour détecter cette demande et la prendre en charge? (le but étant de masquer complètement le processus à l'utilisateur)

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    tu peux regarder à intervalle régulier s'il y a de nouvelles données sur la sortie standard du programme

  3. #3
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    ????
    Je n'ai pas compris.

    Ton application qui envois les messages à l'utilisateur et celle qui répond, c'est la même application ?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Non ce n'est pas la même appli,
    Par exemple je souhaite lancer un .bat depuis une application windows. Pour lancer le processus pas de problème mais à un moment, la commande du .bat fait une demande à l'utilisateur. Or le but de la manoeuvre c'est que l'application graphique remplace l'utilisateur.

    Pour la scrutation de la sortie standart, j'y ai penser mais admettons que celui qui à fait l'appli console que j'éxécute via mon processus soit un parfait idiot et qu'il fasse une demande utilisateur (un truc genre Console.ReadLine()) sans avoir décrit ce qu'il souhaite genre un programme du genre:

    void Main(){
    TraitementLong();
    Console.ReadLine();
    }

    là ca sert plus à rien de vérifier la sortie standart et pourtant, le processus va attendre pour rien.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Après différentes recherches, j'ai trouver la classe ProcessThread qui permet de savoir si un Thread est en attente et pour quelle raison.
    Mais si quelqu'un peut me donner la définition exacte de l'état ThreadWaitReason.UserRequest, ca m'aiderais beaucoup

  6. #6
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    Ok.
    Une dernière question, es tu maitre du contenu du point bat ?
    Par ce que si c'est le cas tu peux gérer l'échange d'information entre le bat et l'application autrement.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Malheureusement pas complètement.
    Je gère les appelle au commande via le .bat mais c'est une de ces commandes auxquelles je ne peux rien changer qui me pose problème car elle fait exactement le genre de bétise que j'ai décrit (Traitement long(); Console.ReadLine()

  8. #8
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    Donc si je comprends bien tu veux repérer lorsque tu es en attente d'une action à partir d'un autre programme.
    Lors de l'interaction, la question est toujours identique ?
    Si oui :
    La redirection de la sortie tu l'as fait vers un fichier et tu analyse ce fichier pour y repérer ou non la question.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Je crois que je vais faire comme ça, tant pis pour les commandes muettes. Mais je vais pas scruter la sortie standart moi même je vais utiliser l'évènement OutputDataReceived

  10. #10
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par mrrenard Voir le message
    Je crois que je vais faire comme ça, tant pis pour les commandes muettes. Mais je vais pas scruter la sortie standart moi même je vais utiliser l'évènement OutputDataReceived

    J'utilisais avant une solution un peu différente pour scruter la sortie standard : je re-dirigeais cette dernière sur un pipe, que je pouvais lire de manière désynchronisé (cette technique permettait même de lire une sortie standard sur un autre poste, via un net-pipe).

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Et voilà pour ceux que ca interesse je viens de trouver comment faire. Voilà le 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
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
     
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
     
    namespace OxardProcessLink
    {
        public delegate void WaitInputEventHandler(object sender, WaitInputEventArgs e);
        public delegate void GotMessageEventHandler(object sender, GotMessageEventArgs e);
     
        public enum MessageType
        {
            Output,
            Error
        }
     
        public class ProcessLink
        {
            #region Membres privés
     
            private Process myProcess;
            private string myOutputString = "";
            private string myErrorString = "";
            private string myLastOutput;
            private System.Threading.Thread myDetector;
            private bool myCanModify = true;
            private bool myAutoKillOnError = false;
     
            #endregion
     
            #region Membres publics
     
            public string OutputString
            {
                get { return myOutputString; }
            }
     
            public string ErrorString
            {
                get { return myErrorString; }
            }
     
            /// <summary>
            /// Obtient ou définit le processus associé.
            /// ATTENTION! Ne modifiez pas les redirections des entrée/sorties du processus cela ne servirait à rien
            /// </summary>
            public Process Process
            {
                get { return myProcess; }
                set 
                {
                    if (myCanModify)
                        myProcess = value;
                    else
                        throw new InvalidOperationException("Vous ne pouvez plus changer de processus car cette propriété à déjà été renseignée et le processus est en cours d'éxécution.");
                }
            }
     
            public bool AutoKillOnError
            {
                get { return myAutoKillOnError; }
                set { myAutoKillOnError = value; }
            }
     
            #endregion
     
            #region Méthodes publiques
     
            public void Start()
            {
                lock ((object)myCanModify)
                {
                    myCanModify = false;
                    myDetector = new System.Threading.Thread(new System.Threading.ThreadStart(DetectAsk));
                    myProcess.StartInfo.UseShellExecute = false;
                    myProcess.StartInfo.RedirectStandardInput = true;
                    myProcess.StartInfo.RedirectStandardOutput = true;
                    myProcess.StartInfo.RedirectStandardError = true;
                    myProcess.EnableRaisingEvents = true;
                    myProcess.ErrorDataReceived += new DataReceivedEventHandler(myProcess_ErrorDataReceived);
                    myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);
                    myProcess.Start();
                    myDetector.Start();
                    myProcess.BeginOutputReadLine();
                    myProcess.BeginErrorReadLine();
                    myProcess.WaitForExit();
                    myProcess.Close();
                    if (myDetector != null && myDetector.IsAlive)
                        myDetector.Join();
                    myCanModify = true;
                }
            }
     
            public void Kill()
            {
                myProcess.Kill();
            }
     
            public void WriteOnInput(string pLine)
            {
                myProcess.StandardInput.WriteLine(pLine);
            }
     
            #endregion
     
            #region Code du Thread
     
            private void DetectAsk()
            {
                try
                {
                    while (!myProcess.HasExited)
                    {
                        myProcess.Refresh();
                        foreach (ProcessThread tmpPT in myProcess.Threads)
                        {
                            if (tmpPT.ThreadState == ThreadState.Wait && tmpPT.WaitReason == ThreadWaitReason.LpcReply)
                            {
                                OnWaitInput();
                                break;
                            }
                        }
                        System.Threading.Thread.Sleep(100);
                    }
                }
                catch { }
            }
     
            #endregion
     
            #region Gestion des évènements
     
            private void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                {
                    myOutputString += e.Data + "\n";
                    OnGotMessage(new GotMessageEventArgs(e.Data, MessageType.Output);
                }
            }
     
            private void myProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                {
                    myErrorString += e.Data + "\n";
                    OnGotMessage(new GotMessageEventArgs(e.Data, MessageType.Error);
                    if (myAutoKillOnError)
                        myProcess.Kill();
                }
            }
     
            #endregion
     
            #region Evènements
     
            public event WaitInputEventHandler WaitInput;
            public event GotMessageEventHandler GotOutputMessage;
            public event GotMessageEventHandler GotErrorMessage;
     
            protected virtual void OnWaitInput()
            {
                if (WaitInput != null)
                    WaitInput(this, new WaitInputEventArgs(myLastOutput));
            }
     
            protected virtual void OnGotMessage(GotMessageEventArgs e)
            {
                if (e.MessageType == MessageType.Output)
                {
                    if (GotOutputMessage != null)
                        GotOutputMessage(this, e);
                }
                else
                {
                    if (GotErrorMessage != null)
                        GotErrorMessage(this, e);
                }
            }
     
            #endregion
        }
     
        public class WaitInputEventArgs : EventArgs
        {
            private string myQuestion;
     
            public string Question
            {
                get { return myQuestion; }
            }
     
            public WaitInputEventArgs(string pQuestion)
            {
                myQuestion = pQuestion;
            }
        }
     
        public class GotMessageEventArgs : EventArgs
        {
            private string myMessage;
            private MessageType myMessageType;
     
            public string Message
            {
                get { return myMessage; }
            }
     
            public MessageType MessageType
            {
                get { return myMessageType; }
            }
     
            public GotMessageEventArgs(string pMessage, MessageType pMessageType)
            {
                myMessage = pMessage;
                myMessageType = pMessageType;
            }
        }
    }

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 141
    Points : 110
    Points
    110
    Par défaut
    Par contre, je suis pas encore pour le test sur WaitReason. Il se peut que la condition se fasse avec ThreadWaitReason.Executive et non ThreadWaitReason.LpcReply

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

Discussions similaires

  1. synchronisation des processus
    Par ouadie99 dans le forum C#
    Réponses: 3
    Dernier message: 10/04/2008, 13h55
  2. Synchronisation de processus
    Par titite dans le forum Administration système
    Réponses: 2
    Dernier message: 04/02/2008, 00h01
  3. synchronisation des processus a l'aide des signaux
    Par dammak_info dans le forum Linux
    Réponses: 1
    Dernier message: 29/12/2007, 08h59
  4. Réponses: 2
    Dernier message: 29/03/2007, 17h43
  5. [Synchronisation des processus] Problème du boulanger
    Par Giovanny Temgoua dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 26/02/2005, 12h40

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