IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Interrompre requête trop longue


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Septembre 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 126
    Par défaut Interrompre requête trop longue
    Bonjour,

    Je souhaiterai interrompre l’exécution d'une requête si pas de retour après un certain temps. Sur le principe ça à l'air simple mais je n'y arrive pas et pourtant j'ai cherché !
    Je précise que la requête à interrompre est le lancement d'une procédure stockée sur DB2, lancé en C# par un OledbCommand (ici nommé "cmd") :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cmd.CommandText = "{CALL MABIB.MONPGM};"
    cmd.ExecuteNonReader();
    Il existe un paramètre "Timeout" dans OleDbcommand mais il ne fonctionne pas sur DB2 visiblement.
    J'ai donc essayé de chercher du coté de l'asynchrone, et j'ai testé à peu près tout ce que j'ai trouvé sur la toile concernant les threads, tasks, ExecuteNonReaderAsync(), await, AsyncCalback etc etc.

    systématiquement mon programme est bloqué durant toute l’exécution de la requête.
    J'ai donc du passer à coté de quelque choses au niveau de la gestion de l'asynchrone...

    Est-ce que quelqu'un a une idée de comment stopper l’exécution de la requête au bout de x secondes par ex ?
    Mon idée aussi naïve soit-elle serait de lancer dans un thread secondaires ma requête, puis dans le thread principal surveiller l'execution du thread secondaire, en vérifiant par ex s'il est terminé toutes les 100ms, et si au bout de 5 sec il n'est pas fini je le kill et je passe à la suite..

    Par avance merci pour votre aide !

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    ca a l'air d'être pris en charge pourtant
    https://www.ibm.com/support/knowledg...tProperty.html

    après oui dans les faits quand on fait quelque chose qui peut potentiellement dépasser quelques centaines de ms on passe sur un autre thread (ou une task qui fait ca)
    et kill le thread killera la connection et arretera la requete (enfin je connais pas db2 mais sur sql server c'est le cas)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre confirmé
    Inscrit en
    Septembre 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 126
    Par défaut
    en fait cette option est valable pour un objet DB2 pour .net
    moi j'utilise le oledb.

    aurais tu un exemple de code qui permet d'appeler ce thread, puis de le kill quelques secondes après ? car dans tout ce que j'ai essayé, mon programme ne reprend pas la main... sauf si bien sur je met juste un Thread.Sleep(2000) par ex.
    mais à partir du moment ou je lance le cmd.ExecuteNonQuery(), ou même le ExecuteNonQueryAsync(), le thread prinicipal reste dessus jusqu'à ce qu'il rende la main...

  4. #4
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Une technique que j'ai déjà vu faire pour créer un timeout sur une tâche asynchrone qui ne le prévoit pas est d'exécuter en parallèle un Task.Delay puis d'attendre la première tâche qui prend fin (Task.WhenAny). Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public async Task<int> ExecuteOrTimeoutCommandAsync(SqlCommand cmd, CancelletionTokenSource cts)
    {
    	Task<int> sqlTask = cmd.ExecuteNonQueryAsync(cts.Token);
    	Task timeout = Task.Delay(30000, cts.Token);
    	Task result = await Task.WhenAny(new [] { sqlTask, timeout });
    	cts.Cancel;
    	if(result == timeout) throw new TimeoutException());	
    	return sqlTask.Result;
    }

  5. #5
    Membre confirmé
    Inscrit en
    Septembre 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 126
    Par défaut
    Merci Noxen très intéressant !

    Comment j'execute cette méthode dans ma tache principale ? j'ai essayé de faire un res = await ExecuteOrTimeoutCommandAsync(cmd, cts), mais j'ai une erreur de compilation : "L'opérateur await peut seulement être utilisé dans une tache async. Marquez cette méthode avec l'opérateur async et modifié son type de retour en Task"... pourtant elle est bien marquée en async et le retour est Task<int>.. j'ai essayé en modifiant le retour en Task uniquement j'ai la même erreur de compilation.

  6. #6
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Je pense que le compilateur parle de ta méthode à toi ; si tu utilises await il faut que ta méthode soit marquée async. Si ce n'est pas possible tu peux aussi utiliser ContinueWith() sur la Task renvoyée par ma méthode et vérifier dedans si la Task en question est en erreur (Faulted), annulée (Cancelled) ou terminée (RanToCompletion) avant d'éventuellement récupérer la valeur de retour.

Discussions similaires

  1. Requête trop longue en VBA
    Par NicoMon dans le forum VBA Access
    Réponses: 4
    Dernier message: 07/08/2007, 10h25
  2. requéte trop longue sous ie
    Par devboy dans le forum Général Conception Web
    Réponses: 2
    Dernier message: 16/05/2007, 16h43
  3. Réponses: 4
    Dernier message: 15/05/2007, 10h10
  4. [Requête] Requête trop longue
    Par Ithilien dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 08/01/2007, 10h58
  5. [MySQL] Requête trop longue ?
    Par Thomas1434 dans le forum PHP & Base de données
    Réponses: 14
    Dernier message: 24/03/2006, 21h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo