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

VB.NET Discussion :

Optimisation de téléchargement/écriture de fichiers


Sujet :

VB.NET

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut Optimisation de téléchargement/écriture de fichiers
    Bonsoir,

    J'ai créé une application qui télécharge sur plusieurs threads/sockets et qui écrit a la fois dans un fichier.

    Pour l'instant voici ce que je fais :

    Tout ce qui suit est dans un backgroundworker et les index etc.. sont géré par une bdd sqlce

    Téléchargement asynchrone avec BeginReceive

    à chaque fois que ma callback est appelée j' "Invoke" un délégué qui va écrire ce qui a été téléchargé, donc ~BUFFER_SIZE dans un fichier, pour l'instant mon BUFFER_SIZE est de 3500 octets.

    Ca veut dire que a chaque fois qu'un paquet est reçu je lui intime l'ordre d'écrire directement mes 3500 octet dans un fichier.

    [mode j'aime bien emmètre des doutes sur des choses évidentes]
    Je pense qu'il faut que je limite un maximum mon nombre de traitement dans mon callBack déjà, pensez vous que l'appel à Invoke surchage ma callback ? a priori non ?
    [/eoj]

    Est-ce que je ne devrais pas plutôt créer mon propre buffer qui ferait par exemple 10Mo et attendre que celui ci soit rempli pour lancer l'écriture du fichier ?

    Le soucis si je fais ca c'est que je risque d'utiliser beaucoup de ram, et si je met par exemple un block_size de 10Mo, ca peut faire super lourd si je met 10 threads par exemple

    Enfin voilà c'est pas évident d'arriver à optimiser

    J'aurais voulu savoir également pourquoi lorsque je me fais par exemple un tableau de byte de taille 4000 octet, et que je lui dit de me télécharger 4000 octet à l'appel de beginreceive mon tableau est trop petit ?

    Quelques bout de mon code :

    Callback de téléchargement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        Public Sub callB(ByVal ar As IAsyncResult)
            Dim current As DBChunk = CType(ar.AsyncState, DBChunk)
            Dim read As Integer = _socket.EndReceive(ar)
            If (read = 0) Then
                _socket.Close()
            Else
                Dim index As Integer = 0
                If (current.current_byte = current.start_byte) Then
                    Dim s As String = Encoding.ASCII.GetString(_buffer, 0, read)
                    If (s.Contains("HTTP/")) Then
                        index += s.IndexOf(vbCrLf & vbCrLf) + 4
                    Else
                        MsgBox("ERREUR, pas de GET dans le paquet c'est CHELOU")
                    End If
                End If
     
                Dim de As New DataDownloadEvent(_buffer, read - index)
                de.CurrentFirstWriteIndex = index
     
                Dim r As New received(AddressOf _form.dlm._dm.worker2)
                de.CurrentChunk = current
                _form.Invoke(r, New Object() {Me, de})
                current.current_byte += read - index
                _socket.BeginReceive(_buffer, 0, READ_SIZE, SocketFlags.None, AddressOf callB, current)
            End If
        End Sub
    Ecriture du fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        Public Sub worker2(ByVal sender As Object, ByVal e As DataDownloadEvent)
            fs.Seek(e.CurrentChunk.current_byte, SeekOrigin.Begin) 
            fs.Write(e.Received, e.CurrentFirstWriteIndex, e.ByteReceived)
            fs.Flush()
            RaiseEvent DataReceived(Me, New DataDownloadEvent(e.ByteReceived))
        End Sub
    Je suis ouvert à toute remarque

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Euh... pourquoi tu fais un Invoke ?

    Invoke, ça sert à exécuter du code sur le thread de l'interface graphique, parce que les autres threads n'ont pas le droit de toucher à l'interface graphique. Mais ta méthode worker2 n'a rien à voir avec ça, elle ne fait qu'écrire dans un fichier...

    Le seul résultat de ton Invoke, c'est que tu fais plein de boulot dans le thread de l'UI, ce qui réduit la réactivité de l'interface.

    Si tu fais ça pour être sûr qu'un seul thread à la fois écrit dans le fichier, il y a d'autres moyens plus adaptés de le faire. Le plus simple est d'utiliser l'instruction SyncLock :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        Private ReadOnly _syncObject As New Object()
     
        Public Sub worker2(ByVal sender As Object, ByVal e As DataDownloadEvent)
            SyncLock _syncObj
                fs.Seek(e.CurrentChunk.current_byte, SeekOrigin.Begin) 
                fs.Write(e.Received, e.CurrentFirstWriteIndex, e.ByteReceived)
                fs.Flush()
            End SyncLock
            RaiseEvent DataReceived(Me, New DataDownloadEvent(e.ByteReceived))
        End Sub
    Le premier thread qui entre dans le bloc SyncLock acquiert un verrou sur l'objet _syncObject. Si un autre thread essaie de rentrer dans ce bloc, il restera bloqué jusqu'à ce que le premier en soit sorti. De cette façon, un seul thread peut exécuter ce code à un moment donné.

    D'une manière générale, évite d'utiliser Invoke pour faire des traitements lourds : utilise le seulement si tu dois accéder à l'interface graphique

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Euh... pourquoi tu fais un Invoke ?

    Invoke, ça sert à exécuter du code sur le thread de l'interface graphique, parce que les autres threads n'ont pas le droit de toucher à l'interface graphique. Mais ta méthode worker2 n'a rien à voir avec ça, elle ne fait qu'écrire dans un fichier...

    Le seul résultat de ton Invoke, c'est que tu fais plein de boulot dans le thread de l'UI, ce qui réduit la réactivité de l'interface.

    Si tu fais ça pour être sûr qu'un seul thread à la fois écrit dans le fichier, il y a d'autres moyens plus adaptés de le faire. Le plus simple est d'utiliser l'instruction SyncLock :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        Private ReadOnly _syncObject As New Object()
     
        Public Sub worker2(ByVal sender As Object, ByVal e As DataDownloadEvent)
            SyncLock _syncObj
                fs.Seek(e.CurrentChunk.current_byte, SeekOrigin.Begin) 
                fs.Write(e.Received, e.CurrentFirstWriteIndex, e.ByteReceived)
                fs.Flush()
            End SyncLock
            RaiseEvent DataReceived(Me, New DataDownloadEvent(e.ByteReceived))
        End Sub
    Le premier thread qui entre dans le bloc SyncLock acquiert un verrou sur l'objet _syncObject. Si un autre thread essaie de rentrer dans ce bloc, il restera bloqué jusqu'à ce que le premier en soit sorti. De cette façon, un seul thread peut exécuter ce code à un moment donné.

    D'une manière générale, évite d'utiliser Invoke pour faire des traitements lourds : utilise le seulement si tu dois accéder à l'interface graphique
    Enfaite, je sais bien que c'est censé freezer l'UI, mais j'ai pas trouvé de méthode Invoke dans les thread par exemple, ca parait être du bricolage total ce que je veux faire, mais pas du tout, enfaite je voudrais que tout soit fait de façon asynchrone pour que mon écriture de fichier plombe pas mon téléchargement (c'est un accélérateur de téléchargement que je fais).


    Donc tu va surement pouvoir m'aider enfaite, je voudrais enfaite lancer X thread au final et j'ai pensé que faire un singleton serait pas mal pour mon DataManager ( la classe qui s'occupe des écriture de fichier ), Enfaite ce que je voudrais c'est :

    Download :2~ beaucoup de thread
    écriture de fichier : 1 thread - 1 instance
    UI : (1 thread)

    Download ---- On sépare bien ici/Pile d'évènements -----> écriture de fichier -----> UI/stats

    Au final je veux hiérarchiser les priorités, je veux pas avoir de lock, je pourrais mais c'est inutile étant donné que là je vais utiliser une pile d'évènement (j'ai déjà utilisé les lock sur d'autres applis, c'est pas que je sais pas les utiliser).

    J'espère que tu vois ce que je veux dire

    Enfaite, j'avais peur dans me lancer dans un système ou un thread créer un autre qui créer un autre ( a noté que j'utilise les backgroundworker pour aller plus vite ), parce que plus j'appel un thread dans un autre, a la fin j'avais peur de perdre le contrôle sur mon UI
    tu crois que je devrais utiliser des thread purs pour faire ce que je veux faire ?


    A noté que j'ai essayé d'utiliser BeginWrite mais c'est un enfer parce que j'appel seek avant et ca déconne, pour un fichier de 19Mo ca me télécharge 246 Mo (alors que sans le fichier est le clone de celui sur le serveur), du coup je vois pas trop comment seek asynchrone

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par anat1212 Voir le message
    je voudrais que tout soit fait de façon asynchrone pour que mon écriture de fichier plombe pas mon téléchargement
    Euh... à moins que tu aies une connexion monstrueusement rapide et/ou un disque extrêmement lent, ce risque est à peu près inexistant...

    De toutes façons, même si le risque existait, tu te retrouverais face à un autre problème : les données téléchargées et pas encore écrites sur le disque doivent être stockées en mémoire en attendant, et la RAM n'étant pas une ressource illimitée, ça se terminerait par une OutOfMemoryException...

    Citation Envoyé par anat1212 Voir le message
    Enfaite, j'avais peur dans me lancer dans un système ou un thread créer un autre qui créer un autre ( a noté que j'utilise les backgroundworker pour aller plus vite ), parce que plus j'appel un thread dans un autre, a la fin j'avais peur de perdre le contrôle sur mon UI
    tu crois que je devrais utiliser des thread purs pour faire ce que je veux faire ?
    Thread ou BackgroundWorker, ça change pas grand chose au final... Le principal avantage du BGW est de déclencher les évènements sur le thread de l'UI, mais tu peux gérer ça manuellement si besoin. Pour ce qui est de créer un thread à partir d'un autre, tu n'as pas besoin de faire ça de toutes façons...

    A mon avis tu te compliques la vie... Plutôt que de réinventer la roue, utilise simplement WebClient.DownloadFileAsync, ça fait très bien le boulot. Je doute que tu arrives à faire quelque chose de plus rapide avec ta technique.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Je ne ferais pas tout ca si je pourrais l'écrire en une fonction

    Je sais bien que mon disque est plus rapide que mes connexions, mais mon appli fait énormément bouger la tête d'écriture du disque dur (j'ai pas de SSD).

    Par exemple dans un fichier de 10 000 000 octet avec 2 thread je vais me mettre à écrire les offset suivants :
    0-4 ko 1023-1027ko 5-8ko 1028-1032
    et ce a une vitesse très rapide, donc vu que j'arrive a avoir 1.4mo/sec (pour l'instant)
    ca fait en gros 350 écriture sur le disque par seconde, je veux pas faire l'idiot mais vu comment en conçu mon logiciel je pense que j'arrive à une limite, et comme tu dis c'est pas non plus une bonne idée de blinder la ram.

    Pourquoi j'utilise pas un code tel que Webclient DownloadFile ou autre ?

    Tout simplement parce que aucune de ces méthode ne fait ce que je recherche, je veux pouvoir binder ma socket sur tel ou tel interface, j'utilise le header Range de HTTP pour faire mon logiciel.

    L'idée est de pouvoir télécharger a partir de N interface internet, pour l'instant j'ai un voisin qui me permet l'accès a sa connexion, j'arriverais donc à 2Mo/seconde si mon logiciel est optimisé.

    Enfaite voici un thread que j'ai créé :
    http://www.developpez.net/forums/d99...-developpeurs/

    Je pense qu'au final je vais avoir
    RANGE_SIZE qui correspond à la taille des bouts à couper ( http range )
    FILE_BUFFER_SIZE qui correspond à la taille ( buffer de téléchargement )
    RECV_BUFFER_SIZE qui correspond au nombre d'octet à lire a chaque fois sur la socket

    Qu'est-ce que tu me conseil comme taille de buffer réseau ?

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par anat1212 Voir le message
    Qu'est-ce que tu me conseil comme taille de buffer réseau ?
    Aucune idée...

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Tu vois quand même que vu ce que je veux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    My.Computer.Network.DownloadFile(address ,destinationFileName)
    Ça, ca ne pourrait pas fonctionner, vu que je veux utiliser obligatoirement plusieurs interfaces réseaux.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    effectivement je ne pense pas que ce soit possible avec WebClient... ni même avec HttpWebRequest d'ailleurs, si ?

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Effectivement, ca n'est pas possible, j'ai déjà essayé avec plusieurs classes parce que j'avais déjà fait un logiciel qui téléchargeait des pages web et j'avais trouvé 4 façon différentes de télécharger, et ce n'est jamais possible de choisir l'interface par laquelle va transiter les données

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par anat1212 Voir le message
    Effectivement, ca n'est pas possible, j'ai déjà essayé avec plusieurs classes parce que j'avais déjà fait un logiciel qui téléchargeait des pages web et j'avais trouvé 4 façon différentes de télécharger, et ce n'est jamais possible de choisir l'interface par laquelle va transiter les données
    Et donc tu gères le protocole HTTP "à la main" avec les sockets ? T'es motivé

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    En fait j'ai l'impression que c'est possible, en utilisant ça :
    http://msdn.microsoft.com/fr-fr/libr...tdelegate.aspx

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Dim request = CType(WebRequest.Create(url), HttpWebRequest)
    request.ServicePoint.BindIPEndPointDelegate = AddressOf SelectNetworkInterface
     
    ...
     
     
    Private Sub SelectNetworkInterface( _
    	servicePoint As ServicePoint, _
    	remoteEndPoint As IPEndPoint, _
    	retryCount As Integer _
        ) As IPEndPoint
     
        ' Retourne le IPEndPoint qui correspond à l'interface que tu veux
     
    End Sub
    Tu peux même utiliser ça en créant une classe héritée de WebClient (il faut overrider la méthode GetWebRequest), pour profiter des fonctionnalités de WebClient tout en ajoutant ce dont tu as besoin

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Ah, merci !

    J'avais cherché mal

    C'est déjà nettement plus sexy, en plus ca s'adapte à mon code, par contre je n'ai pas eu a hériter, Donc d'après toi ca irait plus vite si je sauvegarde dans mon thread de téléchargement ?
    Je vais tenter ca et faire un petit bench.

    Voici mon code pour l'instant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    Public Sub callB(ByVal ar As IAsyncResult)
            Dim current As DBChunk = CType(ar.AsyncState, DBChunk)
            Dim read As Integer = _stream.EndRead(ar)
            If (read = 0) Then
                'MsgBox("Fin du flux")
                _eos = True
            Else
                Dim de As New DataDownloadEvent(_buffer, read)
                de.NetworkInterface = current.adapter
                Dim r As New received(AddressOf _form.dlm._dm.worker2)
                de.CurrentChunk = current
                _form.Invoke(r, New Object() {Me, de})
                current.current_byte += read
                _stream.BeginRead(_buffer, 0, READ_SIZE, AddressOf callB, current)
            End If
        End Sub
     
        Private Function BindIPEndPointCallback(ByVal servicePoint As ServicePoint, ByVal remoteEndPoint As IPEndPoint, ByVal retryCount As Integer) As IPEndPoint
            Return _localIP
        End Function
    A noter que j'ai toujours mon invoke mais je vais de ce pas l'enlever, et c'est plutôt sale je n'ai pas trouvé d'autre moyen pour savoir si je suis a la fin de mon flux que de cette façon,

    Et ensuite ici je check :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
        Public Sub startDownload(ByVal url As String, ByVal dbc As DBChunk)
            Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
            request.AddRange(CInt(dbc.start_byte), CInt(dbc.end_byte))
            request.ServicePoint.BindIPEndPointDelegate = New BindIPEndPoint(AddressOf BindIPEndPointCallback)
     
            Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
            _stream = response.GetResponseStream()
            _stream.BeginRead(_buffer, 0, READ_SIZE, AddressOf callB, dbc)
     
            While _eos = False
                System.Threading.Thread.Sleep(50)
            End While
            _eos = False
        End Sub

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Et donc tu gères le protocole HTTP "à la main" avec les sockets ? T'es motivé
    Heu ouai ^^ je me disais que plus je serais bas niveau plus je pourrais toujours essayer d'optimiser, mais bon je pense que c'est insignifiant pour le goulot qu'est l'accès réseau , donc je pensais ne pas passer par des classes qui font le café et les croissants


    Edit : je viens de penser que je pourrais mettre en shared (static, variable de classe) mon stream de fichier, comme ca chaque instance de ma classe accèdera à un seul stream.

    Mais j'en viens à un autre point, ca veut dire que si je veux faire plusieurs téléchargement en simultané, ca ne marche plus

    Note pour plus tard : faire une liste de filestream

    est-ce une mauvaise idée ?

    ReEdit : je tenais encore à te remercier pour la trouvaille, désormais je chercherais plus.

    D'ailleurs c'est quelque chose de curieux, le serveur IIS ne gère pas les requêtes Range, mais il est implem dans le WebClient par exemple.

  14. #14
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par anat1212 Voir le message
    Je vais tenter ca et faire un petit bench.
    C'est le meilleur moyen d'en avoir le coeur net

    Citation Envoyé par anat1212 Voir le message
    Heu ouai ^^ je me disais que plus je serais bas niveau plus je pourrais toujours essayer d'optimiser
    Ben si tu penses pouvoir faire un meilleur boulot que les gens de chez MS, fais-toi plaisir... mais à mon avis c'est vraiment pas évident.

    Citation Envoyé par anat1212 Voir le message
    Note pour plus tard : faire une liste de filestream

    est-ce une mauvaise idée ?
    Ben c'est surtout pas très pratique... comment tu retrouves le stream qui correspond à un téléchargement donné ?

    Pour moi tu n'as pas besoin de ça de toutes façons. Si tu fais le téléchargement et l'écriture dans le fichier sur le même thread, tu peux tout avoir dans la même méthode, et donc ton FileStream sera juste une variable locale.

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Me revoilà avec un nouveau problème,
    Il semblerait qu'avec les classe que j'utilise, il n'est possible que de faire que 2 téléchargement simultanément, c'est très étrange, j'ai cherché à modifier ce paramètre mais sans succès.
    vidéo

    A noter le Form1 très sexy

    Le blocage se fait a une de ces lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
            _stream = response.GetResponseStream()
    Avez-vous une idée ?

  16. #16
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Je crois que ça vient de ServicePoint.ConnectionLimit, qui vaut 2 par défaut. Tu dois pouvoir changer sa valeur a priori...

  17. #17
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Je crois que ça vient de ServicePoint.ConnectionLimit, qui vaut 2 par défaut. Tu dois pouvoir changer sa valeur a priori...
    Je viens de trouver à la seconde ceci et cela marche très bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ServicePointManager.DefaultConnectionLimit = 10
    Merci quand même

    PS: Ça dépote

  18. #18
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    J'ai beau cherché mais je ne vois pas comment je pourrait raise un event d'un thread à un autre.

    Admettons que j'ai ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    Private _bgws As New List(Of BackgroundWorker)
     
    Public Sub Create()
    Dim bgw As BackgroundWorker
                   For i As Integer = 1 To 2
                        bgw = New BackgroundWorker
                        bgw.WorkerReportsProgress = True
                        bgw.WorkerSupportsCancellation = True
     
                        AddHandler bgw.DoWork, AddressOf work
                        AddHandler bgw.RunWorkerCompleted, AddressOf endofwork
                        AddHandler bgw.ProgressChanged, AddressOf notifywork
     
                        _bgws.Add(bgw)
                        bgw.RunWorkerAsync(New Object() {_adapters(_ips.IndexOf(ip)), ip, dbd})
                    Next
     
       Public Sub work(ByVal sender As Object, ByVal e As DoWorkEventArgs)
                 'traitement
    'Ici je voudrais interagir avec mon voisin bgw(en admettant que je connaisse son index)
        End Sub

  19. #19
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Il n'y a pas de moyen simple de déclencher un évènement (ou plus généralement appeler une méthode) sur un autre thread, sauf si celui-ci exécute une pompe de messages.

    C'est le cas du thread d'interface graphique, où tu peux utiliser Invoke ou BeginInvoke pour mettre un delegate en "file d'attente". Le delegate sera exécuté dès que le thread aura traité les messages précédents (avec éventuellement une gestion de priorité comme dans le Dispatcher de WPF).

    Par contre, pour un BackgroundWorker, tu es coincé, vu que celui-ci exécute sa tâche sur un thread du ThreadPool.

    Donc il faut aborder le problème autrement... qu'est-ce que tu cherches à faire exactement ? Pourquoi as-tu besoin que l'évènement s'exécute sur un thread particulier ?

  20. #20
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 91
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Il n'y a pas de moyen simple de déclencher un évènement (ou plus généralement appeler une méthode) sur un autre thread, sauf si celui-ci exécute une pompe de messages.

    C'est le cas du thread d'interface graphique, où tu peux utiliser Invoke ou BeginInvoke pour mettre un delegate en "file d'attente". Le delegate sera exécuté dès que le thread aura traité les messages précédents (avec éventuellement une gestion de priorité comme dans le Dispatcher de WPF).

    Par contre, pour un BackgroundWorker, tu es coincé, vu que celui-ci exécute sa tâche sur un thread du ThreadPool.

    Donc il faut aborder le problème autrement... qu'est-ce que tu cherches à faire exactement ? Pourquoi as-tu besoin que l'évènement s'exécute sur un thread particulier ?

    J'ai besoin d'éloigner mes accès concurrentiel parce que maintenant tout marche bien et j'utilise un Lock, mais c'est vraiment dommage parce que j'ai perdu /20 fois de débit, donc à partir de là on sait que j'ai Nthread qui téléchargent, et je voudrais pouvoir gérer une pile d'évènements ou quelque chose comme ca pour écrire mon fichier.

    J'ai pas trop compris synchronize a quoi cela était utile dans un FileStream ?

    C'est censé éviter l'accès concurrentiel non ? et pourtant j'avais qq différences de fichier avant de mettre un Lock

    edit: C'est fou j'ai l'impression qu'il y a moins de monde qu'avant sur le forum vb.net, tu es le seul à me répondre ...
    Sur ce, bonne journée

Discussions similaires

  1. [XL-2010] Optimiser le téléchargement de fichiers .csv sur internet via VBA
    Par funtim78 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 08/01/2013, 09h18
  2. Réponses: 16
    Dernier message: 28/02/2011, 22h10
  3. Optimiser l'affichage d'un fichier XML de grosse taille...
    Par UnPeuPerdu dans le forum XML/XSL et SOAP
    Réponses: 11
    Dernier message: 03/06/2004, 16h01
  4. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 4
    Dernier message: 05/02/2003, 08h54
  5. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 11/06/2002, 10h24

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