【问题标题】:C# } For Loop Issues [duplicate]C# } For 循环问题 [重复]
【发布时间】:2016-07-22 12:43:44
【问题描述】:

你好,我的学校有我需要访问的记录,但我忘记了我的用户 ID,所以我制作了一个程序,可以下载任何可能的 PDF 并在其中搜索我的名字。如果它找到我的,它会在程序关闭并说“我们发现一个包含 Sean 文件名的文件是:xxxxxx.pdf”时提醒我是在一个单独的方法!顺便说一句,学校名称将被加星标!

*顺便说一句!在 Search() 中,我使用 i-10 作为临时修复,但我认为它们一定是更好的方法 *


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using BitMiracle.Docotic.Pdf; // pdf parser / viewer
using System.IO;
using System.Threading;

namespace XXXXXXX_TEMP
{
    class Program
{
    static void Main(string[] args)
    {
        Program p1 = new Program();
        p1.Start();
    }

    private void Start()
    {
        WebClient wc = new WebClient();
        for (int i = 200000; i < 999999999; i = i + 10)
        {
            try
            {
                wc.DownloadFile("XXXXXXXXXXXXXXXXXXXXXX/" + i + ".pdf", i + ".pdf");
            }
            catch (WebException) {
                continue;
            }
            PdfDocument pdf = new PdfDocument(i + ".pdf");
            Thread a = new Thread(() => Search(i, pdf));
            a.Start();

            if (i == 999999) {
                Console.ReadLine();
            }
        }
    }

    private void Search(int i, PdfDocument pdf)
    {
        i = i - 10;
        String html = pdf.GetText();
        if (html.ToLower().Contains("sean"))
        {
            Console.WriteLine("Found File Containing Sean! File Name Is : " + i + ".pdf\n");
            Console.WriteLine("PDF Text = " + html);
      }
    }
  }
}

【问题讨论】:

  • 这个非常常见的错误已经在许多其他 Stack Overflow Q&A 中得到解决,包括标记的重复。请特别参阅this answer 以获得很好的解释。
  • @PeterDuniho 非常抱歉,这经常发生在我身上,因为我在措辞上有问题。对不起,下次我会更加小心。

标签: c# multithreading pdf webclient


【解决方案1】:

您遇到的称为closing over the loop variable。您应该仔细研究链接的答案以及它链接到的博客条目。

您的问题的直接解决方案是将i 的副本传递给线程。那就是:

int index = i;
Thread a = new Thread(() => Search(index, pdf));

但是,您可能会发现启动所有这些线程会严重阻塞系统,并且让所有这些线程挂起可能会占用资源并导致内存不足异常。更简洁的方法是调用ThreadPool.QueueUserWorkItem,如下所示:

ThreadPool.QueueUserWorkItem(o => Search(index, pdf));

或者,在较新版本的 .NET 中:

Task.Run(() => Search(index, pdf));

有关“即发即弃”线程的更多信息,请参阅Simplest way to do a fire and forget method in C#?

【讨论】:

  • @SeandaPotato:主要的一点是您的解决方案不正确,因为它可以跳过某些文档并多次处理其他文档。任何速度差异都将在微秒级。 i-10 的东西不可靠。
  • 啊,好吧。还有一个问题,我从 MSDN 中了解到,Task.Run() 是 Task.Facotry.StartNew() 的一种新的更简单的方法,但它确实限制了用户能够做某些事情。让我对 Task.Run 感到困惑的是,它说它运行的是你从线程池中发送的东西。我是否需要创建这个线程池,或者它已经存在。还有 ThreadPool.QueueUserWorkItem(o => Search(index, pdf));我需要在这里创建一个线程池还是由系统再次处理?
  • @SeandaPotato:线程池由系统自动创建和管理。请参阅msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx 了解更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多