【问题标题】:How can i run Class Code in extra Thread? [duplicate]我如何在额外的线程中运行类代码? [复制]
【发布时间】:2020-11-02 16:47:34
【问题描述】:

我想尽快获得 100 个链接的内容。我的第一个想法是创建一个线程,创建 100 个 Webbrowser 对象,让它们导航并收集列表中的所有 html 字符串。但是当我尝试运行我的代码时,我收到错误“实际线程不是单线程公寓”。

我有以下代码:

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();
            }
        }
    }
}

【问题讨论】:

    标签: c# multithreading class


    【解决方案1】:

    您在StartDriver() 方法上应用的 STAThread 属性对您自己的应用程序创建的线程没有影响。

    在调用Start()之前,您需要自己调用SetApartmentState() 使它们成为STA

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

    参考: https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.setapartmentstate

    【讨论】:

    • 谢谢,至少没有报错,但是他为什么不在线程内调用事件方法ClassGetRanking_DocumentCompleted呢?
    • 这可能与您正在导航的链接有关。如果 Document 从未完全加载,则该事件也不会被调用
    • 由于您只需要页面的 HTML 代码,我建议使用 System.Net 类而不是 WebBrowser。这更有趣,使用起来也更安全。例如,您可以使用 HttpClient。这里:docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 2020-01-18
    • 2021-01-12
    相关资源
    最近更新 更多