Avatar billede groyk Novice
22. juli 2007 - 21:44 Der er 6 kommentarer og
1 løsning

App fryser ved brug af "WebRequest"

Hej Har en funktion der returnere om et link eksistere.

Det kører fint, men når funktionen er blevet kaldt nogle gange, "10-20 gange" så fryser programmet.

Alt kører fint hvis jeg fjerner de 3 WebRequest linier.

Her er koden.

Function Online(ByVal UrlS As String) As String
        Try
            Dim Url As New System.Uri(UrlS)
            Dim req As WebRequest = WebRequest.Create(Url)
            Dim resp As WebResponse = req.GetResponse()
        Catch
            Return False
        End Try
        Return True
End Function
Avatar billede driis Nybegynder
22. juli 2007 - 22:55 #1
Et webrequest tager tid; og nogle gange mere end andre. Det er nok det du oplever.

Det mest sandsynlige er, at du kører Online funktionen på samme tråd som GUI tråden. Så er vinduet blokeret, og bliver ikke opdateret mens funktionen kører. Løsningen er at køre den i en separat tråd; eller bruge den asynkronve version af WebRequest.GetResponse (BeginGetResponse). (Asynkron kald er også at køre i en anden tråd, her gør frameworket bare det meste af arbejdet for dig).
Avatar billede groyk Novice
23. juli 2007 - 08:14 #2
Tror du tildels har ret, men det giver mig 2 nye spørgsmål.

1. Funktionen kaldes ud fra en ListBox og en timer, så den hvert 30 sek. tjekker det første Url i listboksen og derefter flytter Url'en ned i bunden, sådan kører det konstant.

Kan problemet så være at den ikke når at få response før timeren tricker igen?

2. Hvordan laver jeg evnt. funktionen om til at køre i en seperat tråd?
Hvis jeg kan det, kan jeg jo fjerne timeren og så bare køre kontinuerligt med en sleep() i funktionen.
Avatar billede driis Nybegynder
23. juli 2007 - 20:20 #3
1. Det er muligt. Eller, det kan være serveren svarer langsommere nu-og-da.

2. Den nemmeste måde at lade funktionen køre kontinuerligt, ville være, at lade en tråd fra ThreadPool'en køre en metode, der gør arbejdet. Pseudo-VB agtigt:

Fra din form, f.eks. i OnLoad, starter du tråden:
ThreadPool.QueueUserWorkItem(checkingFunction)
Her er checkingFunction en delegate der peger på din metode. Den kan så se cirka således ud:
While(condition)
  CheckIfStuffIsOnline
  Thread.Sleep(30000)
End While

Der er lige et par udfordringer her. Dels skal du sikre at funktionen returnerer når dit program bliver lukket. I pseudo eksemplet herover kunne det gøres ved at lade condition bliver false. Endelig, når du skal opdatere elementer på din form, er det vigtigt at det gøres på GUI tråden og ikke på din anden tråd. Det gør du ved at bruge Invoke metoden - et eksempel findes på MSDN, ellers er Google din ven.

Jeg har ikke postet et færdigt eksempel da jeg normalt skriver C# og helt sikkert ville rode for meget rundt i VB syntaksen, til at det ville være nyttigt.
Avatar billede groyk Novice
23. juli 2007 - 21:30 #4
Takker for tippet, men har fået det til at spille på en noget mere simpel måde!

Function Online(ByVal UrlS As String) As String
        Try
            Dim Url As New System.Uri(UrlS)
            Dim req As WebRequest = WebRequest.Create(Url)
            Dim resp As WebResponse = req.GetResponse()
NY LINIE    resp.Close()
        Catch
            Return False
        End Try
        Return True
End Function

Ærgeligt at skulle lede så længe efter en så SIMPEL ting :-)

Du får sku´ point for din indsats.

Tror måske jeg vil prøve den sidste løsning du kom med.
Avatar billede driis Nybegynder
24. juli 2007 - 10:28 #5
Du skal selvfølgelig lukke responset; den havde jeg ikke lige set. Ellers har du 10-20 åbne forbindelser til serveren, og så svarer den før eller senere langsomt eller slet ikke.

Som du selv skriver, bør du nok overveje tråd funktionen alligevel; idet dit GUI per definition ikke bliver opdateret mens funktionen kører.

Endelig vil jeg anbefale at du laver en Finally blok og flytter din resp.Close() derned. Så vil den altid blive kørt, selv hvis GetResponse smider en exception.

Tak for points ;-)
Avatar billede groyk Novice
24. juli 2007 - 11:52 #6
Finally block??

Hvordan gør man det? Kan du lave et simpelt eksempel?
Avatar billede driis Nybegynder
24. juli 2007 - 12:33 #7
Det der står i en finally blok bliver altid kørt, uanset om der sker en exception i try blokken. Således kan du sikre oprydning af ressourcer, selvom der sker en exception.

Function Online(ByVal UrlS As String) As String
        Try
            Dim Url As New System.Uri(UrlS)
            Dim req As WebRequest = WebRequest.Create(Url)
            Dim resp As WebResponse = req.GetResponse()

        Catch
            Return False
        Finally
            resp.Close()
        End Try
        Return True
End Function
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester