Gestion de deux applis simultanées [Résolu]

Hermios 265 Messages postés dimanche 14 avril 2013Date d'inscription 23 mai 2014 Dernière intervention - 22 mars 2011 à 17:34 - Dernière réponse : Hermios 265 Messages postés dimanche 14 avril 2013Date d'inscription 23 mai 2014 Dernière intervention
- 24 mars 2011 à 14:46
Salut à tous,
D'abord, désolé si ma question est simpliste, je suis assez débutant en C# (j'ai plus d'expérience en Java, quoique pour le coup, j'ai jamais réussi à résoudre ce genre de problème non plus!!! )
Voici mon appli :
J'ai une appli qui choisis des données dans une première fenêtre, puis, en cliquant sur ok, ca ferme la fenêtre et lance des fonctions wsdl. J'aimerai que dans le même temps, ca affiche les résultats dans une nouvelle fenêtre d'infos.
Pour ce faire, j'ai tenté
1- De lancer les demandes wsdl, puis l'affichage de la fenêtre d'info
2- De lancer un thread pour une appli, et l'autre dans le thread principal (j'ai essayé les deux cas)
3- De lancer deux threads différents, avec des variables globales

Mes problèmes:
- Ben je réussis à peu près à initialiser ma fenêtre d'info (elle affiche le texte initial, parfois, suivant la structure choisie, parfois rien du tout), par contre, impossible de mettre à jour (Même avec des refreshs un peu partout)

- Si je lance la fenêtre d'info, je dois mettre un while sans fin, sinon, elle ferme immédiatement. Normalement, si les wsdl se lancent ensuite, une fois terminés, une variable globale arrête le thread d'info (oui, je sais c'est bourrin!).
Ca marche à peu prÈs. Cependant, le second thread doit écrire dans le premier, et l'écriture semble ne pas passer.

Comme j'imagine que c'Est pas clair, je vous envoie ci dessous mon code. Si vous avez une idée...

Merci beaucoup de votre aide.

Mon code :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ProgrammeCompilation
{

public partial class JavaProgrammChoice : Form
{
static String selectedValuesFile = "selectedValuesFile.ini";
static List<String> mxJPOFilesList = new List<String>();
static DirectoryInfo ROOT_FILE = new DirectoryInfo("Y:\\Java\\Workspace\\AIDAExportFile");
InfoForm infoForm = new InfoForm();
bool wsdlLaunched = false;
String result="ERROR";

[DllImport("kernel32.dll")]
public static extern bool SetEnvironmentVariable(string VariableName, string VariableValue, EnvironmentVariableTarget target);

public JavaProgrammChoice()
{
InitializeComponent();
recursiveGetJPOFile(ROOT_FILE);
for (int i = 0; i < mxJPOFilesList.Count; i++)
javaProgrammesList.Items.Add(mxJPOFilesList[i]);

String savedPrograms = null;
if (File.Exists(selectedValuesFile))
savedPrograms = File.ReadAllText(selectedValuesFile);

if (savedPrograms != null && savedPrograms != "")
{
Char[] pipe = { '|' };
String[] listSelectedPrograms = savedPrograms.Split(pipe);
for (int i = 0; i < listSelectedPrograms.Length; i++)
if (javaProgrammesList.Items.Contains(listSelectedPrograms[i]))
javaProgrammesList.SetSelected(javaProgrammesList.Items.IndexOf(listSelectedPrograms[i]), true);
}
else javaProgrammesList.SelectedIndex = 0;
}

public void recursiveGetJPOFile(DirectoryInfo parentDirectory)
{
FileInfo[] filesList = parentDirectory.GetFiles();
DirectoryInfo[] dirList = parentDirectory.GetDirectories();
for (int i = 0; i < filesList.Length; i++)
{
FileInfo thisFile = filesList[i];
if (thisFile.FullName.EndsWith("_mxJPO.java"))
{
mxJPOFilesList.Add(parentDirectory.Name + "/" + thisFile.Name);
}
}
for (int i = 0; i < dirList.Length; i++)
recursiveGetJPOFile(dirList[i]);
}

private void launchWSDL(Object inputParam)
{
/*Define the programm*/
CompilationWSDL.COMPILATION_PROGRAMMEClient compilProg = new CompilationWSDL.COMPILATION_PROGRAMMEClient();

/*Connect*/
MessageBox.Show(result);
infoForm.addInfos("Try to connect", true);
//result=compilProg.
infoForm.addInfos(result, false);


if(result.StartsWith("ERROR"))
{
MessageBox.Show("Programm aborted : Connection Impossible");
wsdlLaunched = true;
}
/*For each programm, lauch de compilation*/
Char[] separator={'|'};
String chosenProgramm=(String)inputParam;
String[] chosenProgrammArray=chosenProgramm.Split(separator);
for(int i=0;i<chosenProgrammArray.Length;i++)
{
infoForm.addInfos("Compiling " + chosenProgrammArray[i],true);
result = compilProg.JavaProgrammCompiling(chosenProgrammArray[i]);
infoForm.addInfos(result, false);
}

/*Disconnect*/
infoForm.addInfos("Try to disconnect", true);
//result=compilProg.
infoForm.addInfos(result, false);
MessageBox.Show("Compilation done");
wsdlLaunched = true;
}

private void openInfoWindow(Object chosenProgramm)
{
infoForm.initializedLabel = (String)chosenProgramm;
infoForm.Show();
while (!wsdlLaunched) infoForm.Refresh();
}

private void okButton_Click(object sender, EventArgs e)
{
String chosenProgramm = "";
ListBox.SelectedObjectCollection programmsSelection = javaProgrammesList.SelectedItems;
for (int i = 0; i < programmsSelection.Count - 1; i++)
chosenProgramm = chosenProgramm + programmsSelection[i] + "|";
chosenProgramm = chosenProgramm + programmsSelection[programmsSelection.Count - 1];
Visible = false;


/*Launch wsdl PRogramme, throw a thread*/
ParameterizedThreadStart wsdlPts = new ParameterizedThreadStart(this.launchWSDL);
Thread wsdlThread = new Thread(wsdlPts);
wsdlThread.Start(chosenProgramm);

/*Launch information Window throw a Thread*/
ParameterizedThreadStart infoPts = new ParameterizedThreadStart(this.openInfoWindow);
//infoPts.
Thread infoThread = new Thread(infoPts);
infoThread.Start(chosenProgramm);
Thread.Sleep(100);

/*Save the chosen values the file*/
File.WriteAllText(selectedValuesFile, chosenProgramm);

/*Finish the programs*/
while (!wsdlLaunched) ;
wsdlThread.Abort();
infoThread.Abort();

Close();
}

private void CancelButton_Click(object sender, EventArgs e)
{
Close();
}

private void javaProgrammesList_SelectedIndexChanged(object sender, EventArgs e)
{
}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{

}

private void JavaProgrammChoice_Load(object sender, EventArgs e)
{

}

private void javaProgrammesList_SelectedIndexChanged_1(object sender, EventArgs e)
{

}
}
}



@+. Hermios
Afficher la suite 

Votre réponse

2 réponses

Meilleure réponse
cs_Robert33 835 Messages postés samedi 15 novembre 2008Date d'inscription 14 janvier 2017 Dernière intervention - 22 mars 2011 à 21:12
3
Merci
Bonsoir

Pour arriver à tes fins le meilleur moyen, à mon humble avis, c'est que tes threads generent un évenement, intercepté par la form qui doit afficher l'info.
il faut également faire attention que la form soit invoquable lors de l'affichage, sinon ça plante grave.

Comme je ne sais pas bien comment expliquer , je te donne un exemple

Une class qui va generer des threads,
pour simplifier, la procedure de thread est une des méthodes de la classe et l'evenement est dans la class, donc accessible à tous les threads.

// classe qui va generer les threads
public class MyProcess
{
    //Parametre d'evenement utilisé pour echanger de l'info vers l'exterieur
    public class myEventArgs : EventArgs
    {
        public string ThreadName { get; private set; }
        public string Message { get; private set; }
        public myEventArgs(string threadName, string message)
        {
            Message = message;
            ThreadName = threadName;
        }
    }
    //Evenenement pour echanger de l'info vers l'exterieur
    public event EventHandler<myEventArgs> myEvent;

    // Corps du thread
    private void TrheadProc(Object inputParam)
    {
        for (int i = 0; i < 100; i++)
        {
            if (myEvent!= null)
                myEvent(this, new myEventArgs(inputParam.ToString(), string.Format(" loop #{0}", i)));
            Thread.Sleep(1000);
        }
    }
    
    //Constucteur, permet de créer la forme de visu
    // l'instance de la class est passé en parametre à la form de visu pour lui permetre de s'abonner aux évenement.
    public MyProcess()
    {
        // on crée la form de visu au début.
        Form2 infoForm = new Form2(this);
        infoForm.Show();
    }
    //Lancement d'un thread
    // methode appelée de l'exterieur
    public void StartOneThrread(string ThreadName)
    {
        ParameterizedThreadStart myThreadProc = new ParameterizedThreadStart(this.TrheadProc);
        Thread myThread = new Thread(myThreadProc);
        myThread.Start(ThreadName); 

    }
}


La form de visualisation
Dans mon exemple elle ne possède qu'une listeview, affichée en mode detail avec 2 colonnes (SubItems)
//Form de visu
public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }
    // à la construction on s'abonne à l'évenement en provenance des threads
    public Form2(MyProcess proc) : this()
    {
        proc.myEvent += new EventHandler<MyProcess.myEventArgs>(proc_myEvent);
    }

    //Procédure d'evenement
    //Affiche dans la listview le nom du thread et son message
    //on ajoute une ligne pour chaque thread different
    void proc_myEvent(object sender, MyProcess.myEventArgs e)
    {
        //utilisation d'une procedure d'invoquation pour simplifier les appels
        MethodInvoker mi = delegate() 
        {
            //utilisation d'une listview pour afficher les messages des differents thread
            //S'il y a déjà une ligne pour ce thread, on met à jour le message (subitem2)
            if (listView1.Items.ContainsKey(e.ThreadName))
            {
                listView1.Items[e.ThreadName].SubItems[1].Text = e.Message;
            }
            else //si non on crée une nouvelle ligne
            {
                //nouvelle ligne, premiere colonne le nom du thread, deuxiemme colonne le message
                ListViewItem it=new ListViewItem(new string[]{e.ThreadName,e.Message});
                it.Name = e.ThreadName; //ça c'est pour donner une clef à la collection, pour retrouver la ligne plus tard.
                listView1.Items.Add(it);//le fait d'ajouter la ligne va forcer un refresh sur la listview.
            }
        };

        //On verifie que la form est invoquable et on invoke ou on appel selon le cas.
        if (this.InvokeRequired)
            Invoke(mi);
        else
            mi.Invoke();

    }
}


Enfin le lancement de tout cela, dans une form séparée
L'objet MyProcess est global car la form de visu est generée dans son constructeur, donc si on ne veut qu'une form de visu il ne faut qu'une instance de MyProcess.
Remaque qu'on pourrait par exemple avoir differentes form de visu pour des groupes de threads, il suffit de re-instancier l'objet MyProcess.

private int threadCounter=0;//ça c'est juste pour donner un nom aux threads.
private MyProcess proc = null;
private void button4_Click(object sender, EventArgs e)
{
    if (proc == null)
        proc = new MyProcess();

    proc.StartOneThrread(string.Format("Thread #{0}", ++threadCounter));
              
}


Bon voila j'esper que c'est assez clair

Bon code
Bob.
C# is amazing, enjoy it!

Merci cs_Robert33 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 97 internautes ce mois-ci

Commenter la réponse de cs_Robert33
Hermios 265 Messages postés dimanche 14 avril 2013Date d'inscription 23 mai 2014 Dernière intervention - 24 mars 2011 à 14:46
0
Merci
Hem, je pouvais attendre longtemps une réponse, mon second formulaire n'a jamais été envoyé!!!!
Alors tout d'abord, un grand merci Robert, pour la vitesse de la réponse, et pour le fait qu'elle soit vraiment complète!
J'ai testé ton programme, il fait ce que je veux.
Bon maintenant, me reste plus qu'à le faire fonctionner chez moi!
Merci :)

@+. Hermios
Commenter la réponse de Hermios

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.