Autor Beitrag
nordie92
Hält's aus hier
Beiträge: 3

WinXP, Win7
PHP, Visual C# 2010
BeitragVerfasst: So 17.03.13 13:05 
Moin moin,
ich versuche Bilder aus dem Internet zu laden.
Das klappte auch ganz gut, nur wurde die Bilder hintereinander geladen.
Naja die Lösung schien einfach, Threads für jedes zu ladenen Bild öffnen, fertig!
Naja das war vor 4 Tagen, seit dem habe ich kein Bild mehr zu gesicht bekommen.


Hier mal die Fakten:
- Die "Bildladefunktion" muss so aussehen: public List<Image> GetImages(str Suchwort, Int Limit)
- Ich benutze den .NET Threading-Pool
- Die "Google API" liefert mir die Bild-URLs

Wenn mehr als ein Bild geladen werden soll fliegt diese Exeption:
WaitAll für mehrere Handles in einem STA-Thread wird nicht unterstützt.

Es scheint mir ich mache aus irgendeinem Grund aus meines Hauptthread ein "STA-Thread".

Hier meine BilderSuchKlasse Suchklasse:

ausblenden volle Höhe 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:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Net;
using System.IO;
using Gapi.Search;
using System.Threading;

namespace WindowsFormsApplication1
{
    class GoogleSearchePictures
    {
        private int NumThreads = 0;
        private static string[] inputArray;
        private static Image[] resultArray;
        private static ManualResetEvent[] resetEvents;


        public List<Image> GetImages(string SearcheWord, int Limit)
        {
            SearchResults googleResults = null;
            List<Image> listImage = new List<Image>();
            List<string> listUrl = new List<string>();

            for (int i = 0; i < Limit; ) // Das i++ wurde in das Innere verschoben
            {
                googleResults = Searcher.Search(SearchType.Image, SearcheWord, (i + 1) * 8);
                foreach (SearchResult item in googleResults.Items)
                {
                    listUrl.Add(item.Url);
                    i++;
                }
            }

            NumThreads = listUrl.Count;

            inputArray = new string[NumThreads];
            resultArray = new Image[NumThreads];
            resetEvents = new ManualResetEvent[NumThreads];

            for (int s = 0; s < NumThreads; s++)
            {
                inputArray[s] = listUrl[s];
                resetEvents[s] = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(new WaitCallback(GetImageFromURL), (object)s);
            }

            WaitHandle.WaitAll(resetEvents);

            for (int i = 0; i < resultArray.Length; i++)
            {
                listImage.Add(resultArray[i]);
            }

            return listImage;
        }

        private static void GetImageFromURL(object a)
        {

            int iIndex = (int)a;
            string strUrl = inputArray[iIndex];

            try
            {
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create((string)strUrl);
                HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse();
                Stream stream = httpWebReponse.GetResponseStream();
                resultArray[iIndex] = Image.FromStream(stream);
            }
            catch (Exception){}

            resetEvents[iIndex].Set();
        }
    }
}



Im Anhang das Projekt
Ich hoffe jemand kann mir da helfen, lg nordie92
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von nordie92 am So 17.03.13 15:22, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 17.03.13 13:47 
Hallo nordie92 :welcome:

du schreibst, du hast bisher die Bilder sequentiell geladen, aber durch deine Code-Änderung und Verwendung der WaitHandle.WaitAll-Methode machst du jetzt doch effektiv nichts anderes?

Sinnvoll ist das Auslagern in Threads doch nur, wenn du jedes einzelne Bild sofort anzeigen willst (anstatt darauf zu warten, daß alle geladen sind).
nordie92 Threadstarter
Hält's aus hier
Beiträge: 3

WinXP, Win7
PHP, Visual C# 2010
BeitragVerfasst: So 17.03.13 15:21 
Danke für die schnelle Antwort!
Naja ich hoffe ich verstehe das nicht falsch,
aber ich hatte vorher mit der alten Methode 10 Bilder geladen und
meine Bandbreite hätte viel mehr hergeben können.
Darum nahm ich an das ich mit parallelen Downloads einfach mehr Bandbreite nutzen, stimmts?

Mein "public List<Image> GetImages(str Suchwort, Int Limit)" würde ich gerne so lassen,
ich bin da sehr eigen :P (Mein Hauptprogramm hätte ich immer gerne sehr smart).

lg nordie92


Edit:
Ich weiß auch nicht wie HTTP da arbeitet,
aber der Autentifizierungsvorgang zu den Webservern nimmt doch bestimmt auch Zeit in anspruch die ich durch Threading parallelisieren kann, oder?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 17.03.13 16:01 
Hallo,

naja, auch das Hin- und herschalten zwischen den Threads dauert ja seine Zeit (und ich weiß nicht, ob es nicht eine maximale Anzahl von gleichzeitigen HttpWebRequest gibt).

Aber bezogen auf deinen Fehler könntest du mal versuchen, in einer Schleife auf jedes Event einzeln zu warten:
ausblenden C#-Quelltext
1:
2:
3:
4:
for (int i = 0; i < resetEvents.Length; i++)
{
  resetEvents[i].WaitOne();
}
nordie92 Threadstarter
Hält's aus hier
Beiträge: 3

WinXP, Win7
PHP, Visual C# 2010
BeitragVerfasst: So 17.03.13 16:07 
Super duper gut,
das klappt! Vielen herzlichen dank! Das hätte mir in den 4 Tagen auch ins Auge fallen können :).
Und es geht richtig schnell, nun dauern 8 Bilder 2 Sekunden und verher ca. 20 oder so.

Ich hoffe ich kann mich hier mal revangieren!

lg nordie92