Hermios
Messages postés264Date d'inscriptiondimanche 14 avril 2013StatutMembreDernière intervention23 mai 2014
-
22 mars 2011 à 17:34
Hermios
Messages postés264Date d'inscriptiondimanche 14 avril 2013StatutMembreDernière intervention23 mai 2014
-
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";
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);
/*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();
cs_Robert33
Messages postés834Date d'inscriptionsamedi 15 novembre 2008StatutMembreDernière intervention14 janvier 201733 22 mars 2011 à 21:12
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));
}
Hermios
Messages postés264Date d'inscriptiondimanche 14 avril 2013StatutMembreDernière intervention23 mai 20142 24 mars 2011 à 14:46
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 :)