0

i wanna get the content of 100 links as fast as possible. My first thought was to create one thread, that creates 100 Webbrowser objects, let them navigate and collect all html strings in a list. But when i try to run my code i get the error "actual thread is no singlethread-apartment".

I have the following Code:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    class ClassDriver
    {
        [STAThread]
        public void StartDriver()
        {
            ClassTest t = new ClassTest();

            Thread thread = new Thread(new ThreadStart(t.Collect));
            thread.Start();
        }
    }

    class ClassTest
    {
        private static List<WebBrowser> browsers;
        private static List<string> htmls;
        private static Stopwatch sw = new Stopwatch();

        public void Collect()
        {
            string[] link = { "", "" };
            sw.Start();
            htmls = new List<string>();
            browsers = new List<WebBrowser>();

            for (int a = 0; a < 100; a++)
            {
                browsers.Add(new WebBrowser());
                browsers.Last().DocumentCompleted += ClassGetRanking_DocumentCompleted;
                browsers.Last().Navigate(link[0] + (a + 1) + link[1]);
            }
        }

        private void ClassGetRanking_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser b = (sender as WebBrowser);
            htmls.Add(b.DocumentText);

            if (htmls.Count == browsers.Count)
            {
                sw.Stop();
            }
        }
    }
}

Runner
  • 7
  • 5

1 Answers1

0

The STAThread attribute you applied on StartDriver() method has no effect on the threads created by your own application.

You need to make them STA yourself by calling SetApartmentState() before calling Start()

Thread thread = new Thread(new ThreadStart(t.Collect));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

Ref: https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.setapartmentstate

Alireza
  • 4,976
  • 1
  • 23
  • 36
  • thanks, at least no error, but why doesn't he call the event method `ClassGetRanking_DocumentCompleted` within the thread? – Runner Jul 13 '20 at 13:53
  • That may be related to the links you're navigating. If the Document never fully loads, that event won't also be invoked – Alireza Jul 13 '20 at 14:48
  • 1
    Since you only need the HTML code of the page, I'd suggest using System.Net classes instead of WebBrowser. That's more fun, and also safer to use. You can use HttpClient for example. here: https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient – Alireza Jul 13 '20 at 14:50