Je suis débutant en C# et j'ai un souci avec mon programme.
Quand je le lance le programme, ma fenêtre apparaît bien mais une fois que je démarre une tache elle se fige. Derrière la tache tourne bien (requête sql + check de fichier xlsx) mais plus rien ne bouge à l'écran.
J'ai fait des recherches et apparemment c'est souvent lié à des thread ou des background worker pour d'autres. De mon coté je ne sais pas exactement ce que cela implique et si modifier seulement ma class qui effectue les requêtes va arranger la chose.
Je vous montre la dite class :
using System;
using System.Windows.Forms;
using Oracle.ManagedDataAccess.Client;
namespace ApplicationDoublon
{
public class connexion
{
public void CreateMyOracleDataReader(string[,] tab, int nbcol, int nbline, int compteur, string sourcePath, string destinationPath)
{
string oradb = "Data Source=(DESCRIPTION="
+ "(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=hn)(PORT=1521)))"
+ "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=sn)));"
+ "User Id=usr; Password=psw;";
//Chaine de connexion à la base de données
using (OracleConnection conn = new OracleConnection(oradb))
{
conn.Open();
{
string dosnum;
string nabm;
int index = 0;
int nberror = 0;
string[,] finaltab = new string[nbcol + 1, nbline];
Console.WriteLine(compteur);
for (int i = 0; i < compteur; i++)
{
try
{
dosnum = tab[7, i].ToString();
nabm = tab[12, i].ToString();
//Selectionne le numero d'actes (nabm) et le numero de dossier (dossnum) pour pouvoir requeter dessus
}
catch
{
dosnum = " ";
nabm = " ";
//en cas de cellule vide, remplace les nabm ou dosnum par un espace
}
switch (nabm.Length)
{
case 1:
nabm = "000" + nabm;
break;
case 2:
nabm = "00" + nabm;
break;
case 3:
nabm = "0" + nabm;
break;
//normalise le nabm sur 4 caractere (excel supprime les zero et ils sont obligatoires pour requeter)
}
string sql1 = "select count(dosnum) from KALAM01.hvknabm where dosnum = '" + dosnum + "' and nabm = '" + nabm + "'";
//compte le nombre de numero d'actes reviennent avec le meme numero de dossier dans la base de données
string sql2 = "select typdacc from KALAM01.hrdos where dosnum = '" + dosnum + "'";
//récupere le type d'actes de la ligne (pour facilité le tri via excel plus tard)
string sql3 = "select CODANO FROM HX01.HNACTEREP WHERE codedest = 'EAI_XML' and codano != 'OK'and DOSNUM = '" + dosnum + "' ";
//récupere à chaque passage la derniere ligne du tableau (contient le nombre de fois que reviens un actes sur un numero de dossier)
string sql4 = "select ANOM FROM HX01.HNACTEREP WHERE codedest = 'EAI_XML' and codano != 'OK'and DOSNUM = '" + dosnum + "' ";
//nouveau tableau qui va acceuillir les informations triées
string count = tab[19, i];
string[,] tab2 = new string[nbcol + 1, nbline];
OracleCommand command = new OracleCommand(sql1, conn);
OracleDataReader reader = command.ExecuteReader();
//execution de la requete 1
while (reader.Read() && index < nbline)
{
tab2[20, i] = reader.GetValue(0).ToString();
for (int j = 0; j < nbcol; j++)
{
tab2[j, i] = tab[j, i];
}
index++;
//nouveau tableau combinant le resultat des deux requetes
}
try
{
if (int.Parse(tab2[19, i]) > int.Parse(tab2[20, i]))
{
nberror += 1;
for (int h = 0; h < nbcol + 1; h++)
{
finaltab[h, nberror] = tab2[h, i];
}
}
//compare le tableau extrait du fichier excel avec la base de données tant que la boucle n'est pas au bout de la BDD
//si un actes et un numero de dossier sont présent plus de fois dans le fichier excel que dans la BDD , la ligne est ajoutée au tableau
float avancement = i * 100 / compteur;
Console.WriteLine(avancement + "%");
}
catch { }
OracleCommand command2 = new OracleCommand(sql2, conn);
OracleDataReader reader2 = command2.ExecuteReader();
//execution de la requete 2
//rentre le type d'actes dans le NOUVEAU tableau
while (reader2.Read() && index < nbline)
{
Console.WriteLine(reader2.GetValue(0).ToString());
tab2[15, i] = reader2.GetValue(0).ToString();
}
OracleCommand command3 = new OracleCommand(sql3, conn);
OracleDataReader reader3 = command3.ExecuteReader();
//execution de la requete 3
while (reader3.Read() && index < nbline)
{
Console.WriteLine(reader3.GetValue(0).ToString());
tab2[17, i] = reader3.GetValue(0).ToString();
}
OracleCommand command4 = new OracleCommand(sql4, conn);
OracleDataReader reader4 = command4.ExecuteReader();
//execution de la requete 4
while (reader4.Read() && index < nbline)
{
Console.WriteLine(reader4.GetValue(0).ToString() + " " + dosnum + " OOO");
tab2[18, i] = reader4.GetValue(0).ToString();
}
}
//ferme la connexion à la BDD
conn.Close();
int colonne = finaltab.GetLength(0); //recupere nombre de colonnes
int ligne = finaltab.GetLength(1); // recupere nombre de lignes
var finalTabInver = new string[ligne, colonne + 2];
for (int j = 0; j < nberror; j++)
{
for (int r = 0; r < nbcol + 1; r++)
{
finalTabInver[j, r] = finaltab[r, j];
if (finalTabInver[20, r] != null)
{
try
{
int excelnum = int.Parse(finalTabInver[j, 21]);
int dbnume = int.Parse(finalTabInver[j, 20]);
int difference = excelnum - dbnume;
finalTabInver[j, 22] = difference.ToString();
/* Ce tableau contient toutes les données qui ne sont pas dans la base
avec la difference entre le nombre d'occurences dans le Excel et celui de la BDD */
}
catch { }
}
}
}
writeExcel WriteExcel = new writeExcel();
WriteExcel.CreateExcel(finalTabInver, ligne, sourcePath, destinationPath);
//instanciation de la table writeExcel
}
}
}
}
}
Sur une application lorsque tu lance une tâche par défaut elle utilise le Thread de ton application. Donc tant que ta tâche est exécuté ton application elle ne répond pas.
Je te conseil donc d'ouvrir un BackgroundWorker pour toutes les longues tâches de ton application.
Bon, votre code utilise cette putain d'antiquité qu'est un DataReader, laissez tomber cette cochonnerie pour de simples DataAdapter/DataSet.
N'utiliser pas de requête SQL "dynamique" mais des requêtes paramétrées, bien plus sûr et bien plus maintenable.
Utilisez une seule requête qui utilise intelligemment les jointures externes SQL que cette cascade de requêtes des plus lourdes, inélégantes et surtout sources d'erreurs à répétition.
De la ligne 12 à la ligne 139, une seule requête paramétrée avec jointure externe dans un DataSet via un DataAdapter ne prendrait que quelques lignes très très simples.
L'utilisation des fonctionnalités de "grouping" des DataSet/DataTable/DataView/LINQ permettrait de simplifier les mécanismes de générations des données.
Votre problème initial est un problème qui se produit quand votre méthode prend "trop" de temps.
Le multi-threading est souvent une bonne solution mais cela implique une bien plus grande complexité, donc, on l'évite au maximum quand on le peut.
Si vous gagnez en performance, comme avec mes précédents conseils, vous n'aurez vraisemblablement plus besoin de passer par le multi-threading. Et même si cela ne suffit pas, un code plus simple est bien plus facile à rendre "multi-thread" aware qu'un code complexe avec des requêtes "à tiroirs".
Vous utilisez "using" et c'est très bien mais il reste pas mal d'erreur de débutant.
Votre chaine de connexion, ne la mettez pas dans votre code mais dans votre fichier de configuration, c'est plus simple à gérer et c'est bien plus "sécurisable" que dans le code.
Pas la peine "d'Open" la connexion, c'est totomatique et il faut laisser le framework optimiser le bidule.
Pas de try/catch{}, on ne catche que ce que l'on sait gérer, donc le type de l'exception EST OBLIGATOIRE (et pas Exception, SVP).
Bon avec DataSet, on se débarrasse de tous ces tableaux et boucles foireuses.
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
Je vais tenter d'appliquer toutes vos améliorations
Merci beaucoup
[C#] Application se fige dés qu'on lance action
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Cordialement,
Neross
Vous pouvez m'ajouter sur Discord : Neross#8583