Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 个多线程_C#_Multithreading_Design Patterns - Fatal编程技术网

C# 个多线程

C# 个多线程,c#,multithreading,design-patterns,C#,Multithreading,Design Patterns,我在这里发布了很多关于多线程的文章,伟大的stackoverflow社区在理解多线程方面帮助了我很多 我在网上看到的所有例子都只涉及一个线程 我的申请是一家保险公司(家族公司…全部免费)的刮刀。无论如何,用户可以选择要运行多少线程。例如,假设用户希望应用程序一次抓取5个站点,然后在当天晚些时候,他选择20个线程,因为他的计算机没有做任何其他事情,所以它有多余的资源 基本上,该应用程序构建了一个列表,其中包括1000个要刮取的站点。一个线程启动并执行该操作,更新UI并构建列表 完成后,调用另一个线

我在这里发布了很多关于多线程的文章,伟大的stackoverflow社区在理解多线程方面帮助了我很多

我在网上看到的所有例子都只涉及一个线程

我的申请是一家保险公司(家族公司…全部免费)的刮刀。无论如何,用户可以选择要运行多少线程。例如,假设用户希望应用程序一次抓取5个站点,然后在当天晚些时候,他选择20个线程,因为他的计算机没有做任何其他事情,所以它有多余的资源

基本上,该应用程序构建了一个列表,其中包括1000个要刮取的站点。一个线程启动并执行该操作,更新UI并构建列表

完成后,调用另一个线程来开始刮削。根据用户设置使用的线程数,它将创建x个线程

创建这些线程的最佳方法是什么?我应该在列表中创建1000个线程吗。然后循环通过它们?如果用户设置了5个线程来运行,它将一次循环5个线程

我理解线程技术,但真正吸引我的是应用程序逻辑


<网络上的任何想法或资源都能帮助我吗?

你可以考虑使用线程池:

using System;
using System.Threading;

public class Example
{
    public static void Main()
    {
        ThreadPool.SetMaxThreads(100, 10);

        // Queue the task.
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));

        Console.WriteLine("Main thread does some work, then sleeps.");

        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }

    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo)
    {
        Console.WriteLine("Hello from the thread pool.");
    }
}

您可能想看看关于CodeProject的文章

本质上,您需要创建(并启动)适当的线程数量,在您的情况下,该数量来自用户。每个线程都应该处理一个站点,然后找到下一个需要处理的站点。即使您不使用对象本身(尽管听起来它非常适合您的目的,尽管我显然有偏见!),它也会让您更好地了解这类事情将如何进行。

基本逻辑是:

您有一个队列,在其中放置要刮取的URL,然后创建线程并使用每个线程都可以访问的队列对象。让线程开始一个循环:

  • 锁定队列
  • 检查队列中是否有项目,如果没有,则解锁队列并结束线程
  • 将队列中的第一个项目出列
  • 解锁队列
  • 过程项
  • 调用更新UI的事件(记住锁定UI控制器)
  • 返回到步骤1
  • 只需让线程执行“从队列中获取内容”部分(拉取作业),而不是给它们URL(推送作业),就像你说的那样

    YourThreadManager.StartThreads(用户想要的线程数)


    其他一切都是自动发生的。请参阅其他回复,了解如何创建和管理线程。

    我认为这个示例基本上就是您需要的

    public class WebScraper
    {
        private readonly int totalThreads;
        private readonly List<System.Threading.Thread> threads;
        private readonly List<Exception> exceptions;
        private readonly object locker = new object();
        private volatile bool stop;
    
        public WebScraper(int totalThreads)
        {
            this.totalThreads = totalThreads;
            threads = new List<System.Threading.Thread>(totalThreads);
            exceptions = new List<Exception>();
    
            for (int i = 0; i < totalThreads; i++)
            {
                var thread = new System.Threading.Thread(Execute);
                thread.IsBackground = true; 
                threads.Add(thread);
            }
        }
    
        public void Start()
        {
            foreach (var thread in threads)
            {
                thread.Start();
            }
        }
    
        public void Stop()
        {
            stop = true;
            foreach (var thread in threads)
            {
                if (thread.IsAlive)
                {
                    thread.Join();                      
                }
            }
        }
    
        private void Execute()
        {
            try
            {
                while (!stop)
                {
                    // Scrap away!                      
                }
            }
            catch (Exception ex)
            {
                lock (locker)
                {
                    // You could have a thread checking this collection and
                    // reporting it as you see fit.
                    exceptions.Add(ex);
                }
            }
        }
    }
    
    公共类WebScraper
    {
    私有只读整型线程;
    私有只读列表线程;
    私有只读列表例外;
    私有只读对象锁定器=新对象();
    私人易变bool-stop;
    公共WebScraper(int totalThreads)
    {
    this.totalThreads=totalThreads;
    线程=新列表(totalThreads);
    异常=新列表();
    对于(inti=0;i
    这个刮板,它运行时会占用大量CPU吗

    如果它与这1000个远程站点进行大量通信,下载它们的页面,这可能需要比实际分析页面更多的时间

    您的用户有多少个CPU核?如果它们有2个线程(这在现在很常见),那么除了两个同时执行分析的线程之外,它们不会看到任何速度的提高

    因此,您可能需要“并行”下载页面。我怀疑你是否需要对页面进行同样的分析


    看看异步IO,而不是显式多线程。它允许您并行地启动一系列下载,然后在每次下载完成后都会收到回电。

    如果您真的只是想要该应用程序,请使用其他人已经花费时间开发和完善的内容:

    net是一个完整而全面的.net网络爬虫程序 下载、索引和存储 互联网内容,包括电子邮件 地址、文件、超链接、图像、, 和网页

    无论是感兴趣还是参与 屏幕抓取、数据挖掘、文本 采矿、研究或任何其他 高性能 爬行应用程序是解决问题的关键 你努力的成功, net提供了解决方案 你需要成功

    如果你也想自己写一个,因为它是一件有趣的事情(我不久前写了一个,是的,它很有趣),那么你可以参考arachnode.net提供的这个pdf,它确实详细地解释了一个好的网络爬虫背后的理论:

    下载名为“抓取网络”的pdf(顶部第二个链接)。滚动至第2.6节,标题为:“2.6多线程爬虫”。这就是我用来建立我的爬虫,我必须说,我认为它工作得相当好