Signaler

Problème de thread

Posez votre question Mourad2009B 66Messages postés lundi 23 août 2010Date d'inscription 7 mars 2017 Dernière intervention - Dernière réponse le 21 févr. 2017 à 21:01 par Nessdarth
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 
Utile
+0
plus moins
Bonjour,

copyDirFile n'est pas dans un thread ?
Nessdarth 36Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 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.
Répondre
Mourad2009B 66Messages postés lundi 23 août 2010Date d'inscription 7 mars 2017 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
Répondre
Nessdarth 36Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 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
Répondre
Mourad2009B 66Messages postés lundi 23 août 2010Date d'inscription 7 mars 2017 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é.
Répondre
Nessdarth 36Messages postés vendredi 16 décembre 2016Date d'inscription 28 février 2017 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
Répondre
Donnez votre avis

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.

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

Vous n'êtes pas encore membre ?

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