Entwickler-Ecke

ASP.NET und Web - mysteriöses Phänomen bei Threads


BlackMatrix - Sa 13.02.10 15:42
Titel: mysteriöses Phänomen bei Threads
Mir ist das ganze unbegreiflich. Ich rufe mit vielen Threads Seiten einer Webseite auf.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
            List<Thread> threads = new List<Thread>();
                for(int i=0; i<10;i++)
                {
                    Thread thread = new Thread(new ParameterizedThreadStart(Program.threadsgethtml));
                    threads.Add(thread);
                    thread.Start(mc[i].Value);
                    //Thread.Sleep(200);
                }
                while (threads.Where(t => t.ThreadState != ThreadState.Stopped).Count() > 0) Thread.Sleep(1000);


Ändere ich die Anzahl der Schleifendurchläufe auf 10, werden 5 Threads ordnungsgemäß ausgeführt, ändere ich sie auf 50, werden 25 Threads ordnungsgemäß ausgeführt (scheint also so, als würde es nicht am Server liegen), denn wenn ich den auskommentierten Teil Sleep auf 200ms setze, dann werden etwa 95% der Threads richtig ausgeführt. Kommentiere ich ihn aus, werden immer genau 50% richtig ausgeführt.

Der Rest der Threads bleibt in meiner gethtml Methode stecken und liefert einen Timeout bei "getresponse".

Ich verstehe es einfach nicht. Erst dachte ich, es liegt am Server, aber dadurch dass ich die Anzahl der funktionierenden Anfragen, durch meine Schleife ja varieren kann, muss es an meinem Programm oder an meinem Computer liegen.

Hier noch Zusatzcode:

meine threadsgethtml:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
        private static void threadsgethtml(object o_url)
        {
            string url = (string)o_url;
            string quelltext = gethtml(url);
            Thread.Sleep(zufallszahl);
            string weiterleitung = gethtml(weiterleitung);
        }


und meine gethtml Methode:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
        private static string gethtml(string url)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.CookieContainer = cookiecontainer;
                request.UserAgent = useragent
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                StreamReader sr = new StreamReader(response.GetResponseStream());
                string html = sr.ReadToEnd();
                return html;
            }
            catch { return ""; }
        }


Wäre schön, wenn mir jemand helfen könnte.

P.S: Gleiches Problem, mit weniger Auskunft hier:

http://www.mycsharp.de/wbb2/thread.php?threadid=81542


Kha - Sa 13.02.10 16:32

user profile iconBlackMatrix hat folgendes geschrieben Zum zitierten Posting springen:
Ich verstehe es einfach nicht. Erst dachte ich, es liegt am Server, aber dadurch dass ich die Anzahl der funktionierenden Anfragen, durch meine Schleife ja varieren kann, muss es an meinem Programm oder an meinem Computer liegen.
Hm, das hier funktioniert jedenfalls einwandfrei bei mir:

C#-Quelltext
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:
27:
28:
29:
30:
31:
32:
  class Program
  {
    static void Main(string[] args)
    {
      List<Thread> threads = new List<Thread>();
      for (int i = 0; i < 100; i++)
      {
        Thread thread = new Thread(new ParameterizedThreadStart(Program.threadsgethtml));
        threads.Add(thread);
        thread.Start("http://google.de");
      }
      while (threads.Where(t => t.ThreadState != ThreadState.Stopped).Count() > 0) Thread.Sleep(1000);
    }

    private static void threadsgethtml(object o_url)
    {
      string url = (string)o_url;
      gethtml(url);
    }

    private static void gethtml(string url)
    {
      try
      {
        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader sr = new StreamReader(response.GetResponseStream());
        string html = sr.ReadToEnd();
      }
      catch (Exception e) { Console.WriteLine(e.Message); }
    }
  }


BlackMatrix - Sa 13.02.10 23:42

Du hast recht, ich habe es auch schon an Google ausprobiert, alles kein Problem. Jeder Thread wird korrekt abgearbeitet.

Der einzigste Unterschied, bei mir wird eine autorisierte Anfrage gemacht mithilfe von CookieContainer, ansonsten habe ich keine Ahnung woran es liegen könnte. Nun habe ich es schon an diversen Seiten ausprobiert, bei 30% der Seiten funktioniert es ohne Probleme, ich lasse 50 Threads starten, es werden 50 Threads korrekt abgearbeitet, aber dann gibt es eben auch Webseiten, bei denen ich 30 Anfragen mache und immer, wirklich immer genau die Hälfte korrekt abläuft. Mache ich 25 Anfragen, sind es 13 korrekte.
Es wäre ja verständlich, wenn der Server nicht mehr Anfragen von einer IP zulässt und deswegen der Timeout hervorgerufen wird, aber ich kann wie gesagt ja die Zahl nach oben schrauben auf z.B. 60, dann würden 30 ausgeführt werden. Dadurch wird das ganze ja Problem so mysteriös.
Ich hatte auch schon in Betracht gezogen, dass es vielleicht an meinem Computer oder an meinem Router liegen könnte?!

edit:

Es wird immer geiler. Ich habe mal einen weiteren response eingefügt, sodass wenn ein Timeout ausgelöst wird, es noch einmal versucht wird.

Phänomen:

Es werden bei 20 Schleifendurchläufen, 10 korrekt abgearbeitet, restlichen 10 liefern einen Timeout, die 10 werden durch den try catch Block erneut ausgeführt. Nun werden 5 von den verbleibenden 10 korrekt ausgeführt, und die anderen 5 liefern wieder einen Timeout.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
            try
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.CookieContainer = cookiecontainer;
                HttpWebResponse response;
                try { response = (HttpWebResponse)request.GetResponse(); }
                catch { response = (HttpWebResponse)request.GetResponse(); }
                StreamReader sr = new StreamReader(response.GetResponseStream());
                string html = sr.ReadToEnd();
                return html;
            }


c#surfer - Di 16.02.10 00:14

Falls das Problem noch aktuell ist: Laut deiner Beschreibung tippe ich darauf, dass der Server nur eine bestimmte Anzahl von Verbindungsversuchen von der selben IP pro Zeiteinheit zulässt. D.h. der erste Zugriff klappt, der zweite kommt zu schnell nach dem Ersten und wird ignoriert, der dritte klappt wieder .....


BlackMatrix - Di 16.02.10 00:50

user profile iconc#surfer hat folgendes geschrieben Zum zitierten Posting springen:
Falls das Problem noch aktuell ist: Laut deiner Beschreibung tippe ich darauf, dass der Server nur eine bestimmte Anzahl von Verbindungsversuchen von der selben IP pro Zeiteinheit zulässt. D.h. der erste Zugriff klappt, der zweite kommt zu schnell nach dem Ersten und wird ignoriert, der dritte klappt wieder .....


Vielen Dank.

Das wird mit Sicherheit die Lösung des Problemes sein, denn das würde auch erklären, wieso immer genau die Hälfte der Anfragen funktioniert.


BlackMatrix - Mi 17.02.10 13:33

Wie erreiche ich nun, dass die Anzahl der Thread die aufgerufen werden auch möglichst korrekt laufen?

Ich kann zwar den Sleepbefehl nach jedem Start des Threadaufrufes einbauen, der dafür sorgt, dass 80% funktionieren, dann habe ich aber immer noch das Problem, dass wenn mehrere Threads die Anfrage zur gleichen Zeit machen, die Anfrage abbrechen?

Ich müsste ja dann in meiner gethtml immer dafür sorgen, dass maximal 1 Thread auf

C#-Quelltext
1:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();                    

zugreift.


c#surfer - Mi 17.02.10 19:25

Da du nicht den Zeitpunkt kennst, wann der request rausgeht, musst du dich darüber vom Thread informieren lassen. Dazu schau dir den BackgroundWorker an, da geht es recht einfach mit dem Zurückliefern von Ergebnissen aus einem Thread.