Savoir, dans une fonction, si on est dans le thread principal [Résolu]

MGD Software 76 Messages postés vendredi 1 septembre 2006Date d'inscription 20 avril 2018 Dernière intervention - 15 oct. 2017 à 10:53 - Dernière réponse : Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention
- 15 oct. 2017 à 17:49
Bonjour,
J'ai dans mon programme une fonction qui est soit lancée dans un thread asynchrone, soit appelée directement par un menu de la fenêtre principale.

Or le comportement de cette fonction doit dépendre de la méthode d'appel. Ou encore, l'appel direct doit pouvoir savoir comment s'est terminée la fonction. Mais comme cette dernière est également appelée par un Thread.Start(), elle ne peut être que void (à ma connaissance), et donc ne peut pas renvoyer de résultat.

Je voudrais éviter d'utiliser un BackgroundWorker, qui me paraît être un marteau-pilon pour écraser une mouche. Je suppose qu'il existe un moyen de récupérer un identificateur du thread courant et celui du thread principal, ou de savoir si on est dans un thread asynchrone ou non. En fonction de cela, je pourrais effectuer dans ma fonction les actions nécessaires à l'appel direct.

Bien sûr, je pourrais faire deux fonctions distinctes, mais j'ai horreur de dupliquer du code, pour des raisons de maintenance évidentes.

Une solution ?
Afficher la suite 

9 réponses

Répondre au sujet
Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention - 15 oct. 2017 à 11:30
0
Utile
Bonjour

un peu de code pour mieux visualiser s'il te plait.
Commenter la réponse de Whismeril
MGD Software 76 Messages postés vendredi 1 septembre 2006Date d'inscription 20 avril 2018 Dernière intervention - 15 oct. 2017 à 12:31
0
Utile
Bonjour Whismeril. Toujours là en permanence, à ce que je vois.

Voila le code. Je ne mets pas tout, sinon ce sera difficilement lisible en raison de son volume.

Principe : recherche d'une mise jour en tâche de fond par lecture d'un fichier web donnant la dernière version. Si une mise à jour est trouvée, la fonction continue en téléchargeant et lançant le package d'installation.
- Lors du démarrage de l'application, la fonction est lancée dans un thread asynchrone. S'il n'y a pas de mise à jour à faire, ou une erreur de connexion, la fonction se termine "sans bruit". L’utilisateur n'est pas informé.
- Lorsque l'utilisateur clique sur le menu "Rechercher une mise à jour", et qu'il y en a pas ou qu'il y a une erreur de connexion, il faudrait pouvoir afficher un message "Pas de mise à jour disponible" ou "Erreur de connexion".

Voir les commentaires entre /* --- et --- */


Dans l'évènement load de la feuille principale :
private void wMain_Load(object sender, EventArgs e)
{
[...]
    // Lancement de la recherche de mise à jour
    Thread UpdSearch = new Thread(new ThreadStart(DoUpdSearch));
    UpdSearch.Start();
}

Dans le menu "Rechercher une mise à jour" :
private void mnuHelpUpdateSearch_Click(object sender, EventArgs e)
{
    DoUpdSearch();
}

Et le code partiel de la fonction :
public static void DoUpdSearch()
{
    string sCurrentVersionString = Application.ProductVersion;
    string sCode;
    using (WebClient HttpClient = new WebClient())
    {
        try
        {
            sCode = HttpClient.DownloadString(mksHttpBase + Application.ProductName + ".version.txt");
        }
        catch { return; }
        HttpClient.Dispose();
    }
/* --- Ici, dans le cas d'une erreur (fichier non dispo, pas de connexion), 
il faut qu'il y ait un message dans le cas de l'appel par menu, 
mais pas dans le cas d'un thread séparé. --- */

    Regex Rx = new Regex(@"([0-9]+)\.([0-9]+)\.([0-9]+)");
    Match found = Rx.Match(sCode);

    if (found.Success)
    {
        string[] sCurVersionArray = Application.ProductVersion.Split('.');
        float fCurVersion =
            float.Parse(sCurVersionArray[0]) +
            float.Parse(sCurVersionArray[1]) / 1000 +
            float.Parse(sCurVersionArray[2]) / 1000000;

        string sNewVersion = found.Groups[0].Value;
        float fNewVersion =
            float.Parse(found.Groups[1].Value) +
            float.Parse(found.Groups[2].Value) / 1000 +
            float.Parse(found.Groups[3].Value) / 1000000;

        if (fNewVersion <= fCurVersion)
            return;
/*  --- Ici, dans le cas du return, il faut qu'il y ait un message 
dans le cas de l'appel par le menu, mais pas dans le cas d'un 
thread séparé.  --- */

[...]
/* --- Ici le code télécharge et installe le package, avec dialogue 
avec l'utilisateur, donc comportement identique dans les deux cas --- */
}
Commenter la réponse de MGD Software
NHenry 14129 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 19 avril 2018 Dernière intervention - 15 oct. 2017 à 12:56
0
Utile
Si tu as besoin de l'appeller avec un retour void à un moment et d'avoir un retour à un autre, la solution la plus simple consiste en une fonction qui retourne toujours un résultat et quand tu veux un void, tu créé juste une méthode qui appelle la fonction, du genre :

MyType MaFonction(){}

void MaFonctionSansRetour(){MaFonction();}

Commenter la réponse de NHenry
Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention - 15 oct. 2017 à 13:23
0
Utile
Ou alors tu mets un paramètre dans ta signature

 public static void DoUpdSearch(bool ClickUtilisateur = false)
{
...
if (ClickUtilisateur)
 MessageBox.Show("Le message");
...





private void mnuHelpUpdateSearch_Click(object sender, EventArgs e)
{
    DoUpdSearch(true);
}


pas de changement pour l'autre appel
Commenter la réponse de Whismeril
MGD Software 76 Messages postés vendredi 1 septembre 2006Date d'inscription 20 avril 2018 Dernière intervention - 15 oct. 2017 à 16:23
0
Utile
Ca, c'est évident et j'avais bien sûr déjà essayé.

Mais le compilateur n'est pas du tout d'accord dans la création du thread :
Dans la ligne :
Thread UpdSearch = new Thread(new ThreadStart(DoUpdSearch));

il me dit :
Aucune surcharge pour 'DoUpdSearch' ne correspond au délégué 'ThreadStart'	D:\Documents\_Portable\Csharp\SynchroDir 3\Sources\wMain.cs


Mais comme ça m'a fait réfléchir à un moyen de passer outre, j'ai cette fois pensé à créer une surcharge de ma fonction. Et ça fonctionne.
L'appel par le thread n'est pas modifié. L'appel par le menu comporte le paramètre true qui déclenche les messages.

Voici le code de la fonction et sa surcharge :
// Recherche de mise à jour. Cette fonction est exécutée dans un thread à part et lancée par wMain_Load
public static void DoUpdSearch()
{
    DoUpdSearch(false);
}

public static void DoUpdSearch(bool direct = false)
{
    string sCurrentVersionString = Application.ProductVersion;
    string sCode;
    using (WebClient HttpClient = new WebClient())
    {
        try
        {
            sCode = HttpClient.DownloadString(mksHttpBase + Application.ProductName + ".version.txt");
        }
        catch
        {
            HttpClient.Dispose();
            if (direct)
                MessageBox.Show("Le fichier de définition de version n'a pu être trouvé.\n" + 
                                "Vérifiez éventuellemnt votre connexion Internet.",
                                "Mise à jour", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }
        HttpClient.Dispose();
    }

    Regex Rx = new Regex(@"([0-9]+)\.([0-9]+)\.([0-9]+)");
    Match found = Rx.Match(sCode);

    if (found.Success)
    {
        string[] sCurVersionArray = Application.ProductVersion.Split('.');
        float fCurVersion =
            float.Parse(sCurVersionArray[0]) +
            float.Parse(sCurVersionArray[1]) / 1000 +
            float.Parse(sCurVersionArray[2]) / 1000000;

        string sNewVersion = found.Groups[0].Value;
        float fNewVersion =
            float.Parse(found.Groups[1].Value) +
            float.Parse(found.Groups[2].Value) / 1000 +
            float.Parse(found.Groups[3].Value) / 1000000;

        if (fNewVersion <= fCurVersion)
        {
            if(direct)
                MessageBox.Show("Aucune mise à jour disponible.",
                                "Mise à jour", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }
[...] /* Le reste du traitement est inchangé puisqu'il y a toujours dialogue */
}


Merci pour le support 7/24.
Commenter la réponse de MGD Software
Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention - 15 oct. 2017 à 16:38
0
Utile
1
Ha le paramètre facultatif ne plaît pas au thread...
Alors tu peux aussi passer le paramètre
https://stackoverflow.com/questions/1195896/threadstart-with-parameters
Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention - 15 oct. 2017 à 16:40
En aparté, pour ta regex, tu peux remplacer [0-9] par \d
Commenter la réponse de Whismeril
MGD Software 76 Messages postés vendredi 1 septembre 2006Date d'inscription 20 avril 2018 Dernière intervention - 15 oct. 2017 à 17:34
0
Utile
1
La solution ne m'est plus nécessaire puisqu'une simple surcharge suffit dans mon cas, mais je vais en garder la trace pour le jour où j'aurais vraiment des paramètres à passer à un thread.

J'avais cherché sur le net comment passer des paramètres à un thread, mais je n'ai trouvé que des usines à gaz, bien loin de la solution fournie par JaredPar.

Mais auparavant, il faut que je comprenne vraiment comment fonctionnent les expressions lambda. Je vais relire la page 198 de mon bouquin, que j'ai manifestement survolée d'un peu trop haut.

Merci pour le lien.

>> En aparté, pour ta regex, tu peux remplacer [0-9] par \d
Oui, je sais, mais c'est une vieille habitude prise dans les langages qui ne connaissent pas \d. Surtout que dans la plupart des cas, on y ajoute
a-zA-Z... Et pour cette fonction, je ne recherche pas la performance.
Whismeril 11407 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 20 avril 2018 Dernière intervention - 15 oct. 2017 à 17:49
Je ne pense pas que ce soit plus performant, c’est juste plus rapide à écrire.

[0-9a-zA-Z] => \w, enfin presque, il accepte le . aussi
Commenter la réponse de MGD Software

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.