Menu

Problème de thread [Fermé]

Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 16 févr. 2017 à 17:30 - Dernière réponse : Nessdarth 36 Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 Dernière intervention
- 21 févr. 2017 à 21:01
Bonjour à tous,
J’essaye de créer une application qui me permet de sauvegarder un fichier ou un répertoire d’origine vers un répertoire de destination.
Le problème c’est que quand le processus de copie commence, la fenêtre de l’application devient bloquante, c’est-à-dire que je ne peux même pas la réduire ou la fermée e avant que la copie ne soit terminée.
Pour cela j’ai pensé à utiliser les threads, alors j’ai procédé comme suit :
J’ai créé la fonction suivante :
Remarques : j’ai remplacé une partie du code par des points, afin de réduire la taille du message)
int copyDirFile(string sourceFolderString, string destFolderString, ARG_INFO_STRUCT& Info_structureRecu)
{
if(TEMOIN_CREER_THREAD)
{
QMessageBox::information(0, "TEMOIN_CREER_THREAD", "TEMOIN_CREER_THREAD");
Info_struct_local = Info_structureRecu;
}

qDebug() << "je suis bien dans la fonction copyDirFile";
replace(sourceFolderString.begin(), sourceFolderString.end(), '/','\\');
replace(destFolderString.begin(), destFolderString.end(), '/','\\');

const char* sourceFolder = sourceFolderString.c_str();
const char* destFolder = destFolderString.c_str();

//******************************************
//Si c'est un fichier
FILE* sourceFile = fopen(sourceFolder, "rb");
if(sourceFile != NULL)
{
//On recupère le nom de fichier, on convertit de char a string pour pouvoir faire des manipulations
string baseNameFile = sourceFolder;
baseNameFile = baseNameFile.substr(baseNameFile.find_last_of("\\")+1, baseNameFile.size());
//On crée le fichier final de déstination
……………………..
………………………………………

fclose(sourceFile);

ARG_COPY_FILE Copy_file_struct = {
Copy_file_struct.source = sourceFolder,
Copy_file_struct.destination = destFolderComplet,
};


if(pthread_create(&thread_copy, NULL, &copyFile, (void*)&Copy_file_struct))
return 5;

if(pthread_join(thread_copy, NULL))
return 8;

//majInfos2();

}
//Si ce n'est pas un fichier
else
{
//On doit tester pour savoir si c'est un répertoire, on essayant de l'ouvrir
DIR *dir = opendir(sourceFolder);
struct dirent *ent;
//Si l'ouverture s'est bien déroulée, donc c'est un répertoire
if(dir != NULL)
{
//On récupère la base du nom du répertoire d'origine pour l'utiliser à créer le répertoire de destination.
……………………………………….
//On met le curseur en position 2 pour éviter le (.) et les (..) des répertoires actuel et précédent.
seekdir(dir,2) ;
//On liste tous les élément contenus dans le répertoire
while ((ent = readdir (dir)) != NULL)
{
//On forme le fichier ou le repertoire de déstination, tout dépend de l'élément qu'on va lire
…………………………………………….
//On ouvre le fichier
FILE* fichier = fopen(actualFolderSource, "rb");
ARG_COPY_FILE Copy_file_struct = {
Copy_file_struct.source = actualFolderSource,
Copy_file_struct.destination = destFolderComplet,
//Copy_file_struct.mutex = PTHREAD_MUTEX_INITIALIZER,
};
//Si c'est un fichier
if(fichier != NULL)
{
//*source = sourceFolder; *dest = destFolderComplet;
Maj_struct_local.source = actualFolderSource;
Maj_struct_local.destination = destFolderComplet;

//On crée les thread

if(pthread_create(&thread_copy, NULL, &copyFile, (void*)&Copy_file_struct))
return 5;
if(pthread_join(thread_copy, NULL))
return 8;

fclose(fichier);
}
//Si ce n'est pas un fichier donc c'est surement un réperoire, on appelle donc récursivement la même fonction
else
copyDirFile(actualFolderSource, fullNameDirDest, Info_struct_local);
}
}
//Ce n'esi pas un fichier et ce n'est pas un répertoire
else
return 3;
}
//Si on arrive jusqu'ici, cest que tout est bien passer
return 0;
}


Et voici la fonction copyFile :
void *copyFile(void *arguments)
{
qDebug() << "je suis bien dans la fonction copyFile";
qDebug() << "temoin = " << TEMOIN;
ARG_COPY_FILE *args = (ARG_COPY_FILE *)arguments;
//On définit les fichiers sources et déstination
FILE* fSrc;
FILE* fDest;
char buffer[1024];
int NbLus;
//On ouvre le fichier source
if ((fsrc=""open(args->source, "rb")) == NULL)
{
//On retourne 1 pour dire que le fichier source n'a pas était ouvert.
pthread_exit(NULL);
}
//On ouvre le fichier destination
if ((fDest = fopen(args->destination, "wb")) == NULL)
{
//On ferme le fichier source
fclose(fSrc);
//On retourne 2 pour dire que le fichier de déstination n'a pas était ouvert
pthread_exit(NULL);
}

//Si tout se passe bien on lit les données du fichier source et on les enregistre dans le fichier de déstination
while ((NbLus = fread(buffer, 1, 1024, fSrc)) != 0)
fwrite(buffer, 1, NbLus, fDest);


//On ferme les deux fichier
fclose(fDest);
fclose(fSrc);

Info_struct_local.textEdit->append("copie de " + QString::fromStdString(Maj_struct_local.source) + " vers " + QString::fromStdString(Maj_struct_local.destination));
//Info_struct_local.textEdit->update();
Info_struct_local.progressBarre->setValue(Info_struct_local.progressBarre->value()+1);
//On retourne 0 pour dire que tout c'est bien passé
pthread_exit(NULL);
}

Le problème c’est que la fenêtre est toujours bloquante.

Et c’est pour cela que j’ai besoin de vos lumières
Merci d’avance pour votre aide.
Afficher la suite 

7 réponses

Nessdarth 36 Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 Dernière intervention - 17 févr. 2017 à 10:06
0
Utile
6
Bonjour,

copyDirFile n'est pas dans un thread ?
Nessdarth 36 Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 Dernière intervention > Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 17 févr. 2017 à 19:25
Justement, c'est copyDirFile qui prendra le plus de charge il me semble, donc autant que cette lourde charge s'exécute dans un thread,et si j'ai bien lu, avec le code actuel, tu vas créer n threads, alors que si tu exécutes la 1ere occurrence de copyDirFile, toutes les autres occurrences se feront dans ce seul et même thread.
Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 21 févr. 2017 à 16:29
Bonjour à tous,
Je vous remercie pour les conseils et les suggestions que vous avez voulu m’en faire profiter.
Après plusieurs modifications, je me suis résigné à utiliser
QCoreApplication::processEvents();

Car je crois que les thread ne sont pas adaptés à ma structure de code, vue que je vais modifier les valeurs d’un QProgressBar et le contenu d’un QTextEdit, et comme les thread ne permettent pas de communiquer avec les objets de l’interface graphique, donc j’ai choisi de rester dépéndant de Qt et d’utilisé
QCoreApplication::processEvents(); dans la boucle while de la fonction copyFile.
Et avec ça j’arrive à interagir avec mon interface graphique pendant le processus de copie.
En tout cas merci encore pour vos réponses
Nessdarth 36 Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 Dernière intervention > Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 21 févr. 2017 à 16:37
Sinon pour info, tu peux communiquer vers le thread principal qui peut recevoir des messages du thread secondaire.

En utilisant un postMessage, par exemple, qui sera capté par le thread principal (celui qui gère l'interface graphique).

Par contre je ne connais pas l'équivalent de la fonction PostMessage pour Qt
Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 21 févr. 2017 à 17:02
merci Nessdarth, je vais continuer à chercher une solution avec les thread, mais pour l'instant je vais finaliser mon programme avec Qt, pour pouvoir l'utilisé.
Nessdarth 36 Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 Dernière intervention > Mourad2009B 74 Messages postés lundi 23 août 2010Date d'inscription 19 avril 2018 Dernière intervention - 21 févr. 2017 à 21:01
oui tu as raison et en programmation, il n'y a pas une seule solution possible