1

我想使用httpwebrequest并从给定范围的页面中获取数千条记录来访问 Web 服务器。对网页的每次点击都会获取 15 条记录,并且网络服务器上几乎有 8 到 10000 个页面。这意味着服务器总共有 120000 次点击!如果使用单个进程轻松完成,则该任务可能非常耗时。因此,多线程是想到的直接解决方案。

目前,我已经创建了一个用于搜索的工作类,该工作类将产生 5 个子工作者(线程)以在给定范围内搜索。但是,由于我在线程方面的新手能力,我无法使其工作,因为我无法同步并使它们一起工作。我知道 .NET 中的委托、操作、事件,但是让它们与线程一起工作变得令人困惑。这是我正在使用的代码:

public void Start()
{
    this.totalRangePerThread = ((this.endRange - this.startRange) / this.subWorkerThreads.Length);
    for (int i = 0; i < this.subWorkerThreads.Length; ++i)
    {
        //theThreads[counter] = new Thread(new ThreadStart(MethodName));
        this.subWorkerThreads[i] = new Thread(() => searchItem(this.startRange, this.totalRangePerThread));
        //this.subWorkerThreads[i].Start();
        this.startRange = this.startRange + this.totalRangePerThread;
    }

    for (int threadIndex = 0; threadIndex < this.subWorkerThreads.Length; ++threadIndex)
        this.subWorkerThreads[threadIndex].Start();
}

searchItem 方法:

public void searchItem(int start, int pagesToSearchPerThread)
{
    for (int count = 0; count < pagesToSearchPerThread; ++count)
    {
     //searching routine here
    }
}

线程的共享变量之间存在问题,谁能指导我如何使其成为线程安全的过程?

4

2 回答 2

1

第一个答案是这些线程实际上并不需要那么多工作来共享变量(假设我理解正确)。它们有一些共享的输入变量(例如目标 Web 服务器),但它们是线程安全的,因为它们没有被更改。计划是他们将建立一个数据库或一些包含他们检索到的记录的数据库。您应该让这五个中的每一个都填写自己的输入存档,然后在所有子工作线程完成后将它们合并到一个线程中。如果您用于存储数据的架构以某种方式变得昂贵......那么,您计划存储多少以及计划将其存储在什么变得相关,那么,也许您可​​以分享什么那些是?

于 2013-03-22T18:57:03.433 回答
1

您面临的真正问题是Thread构造函数中的 labmda 表达式正在捕获外部变量 ( startRange)。修复它的一种方法是复制变量,如下所示:

for (int i = 0; i < this.subWorkerThreads.Length; ++i)
{
    var copy = startRange;
    this.subWorkerThreads[i] = new Thread(() => searchItem(copy, this.totalRangePerThread));
    this.startRange = this.startRange + this.totalRangePerThread;
}

有关创建和启动线程的更多信息,请参阅 Joe Albahari 的优秀电子书(还有一个关于捕获变量的部分更进一步)。如果您想了解闭包,请参阅问题。

于 2013-03-22T19:12:22.903 回答