网站程序自带的采集器采集文章(编程不能死记硬背死记硬背,要靠多实践操作(图))

优采云 发布时间: 2022-04-02 05:20

  网站程序自带的采集器采集文章(编程不能死记硬背死记硬背,要靠多实践操作(图))

  编程不能死记硬背,需要多练习

  今天的互联网越来越发达,共享文件就是这么简单。尤其是配合电驴、迅雷等下载软件,更是如虎添翼。从 Internet 上下载几个千兆字节的文件真的很容易。好了,废话太多了,直接进入我们今天的话题吧。

  要像迅雷一样实现多线程下载,核心问题是要明确多线程的概念以及如何实现。

  当然,本文技术含量很低,请直接绕道。

  多线程相对于单线程。详细请参考百度百科中的解释:

  每个程序运行都有一个基本的主线程,用于处理界面绘制、人机交互、后台处理等进程。因此,如果在单线程程序中操作耗时的动作,主界面会非常卡顿。它甚至不起作用。所以,不管你喜不喜欢,最好不要用主线程包罗万象,否则很难给用户带来舒适的客户体验。

  那么如何在C#中实现多线程呢?

  让我们实现一个最简单的多线程示例;

  为了演示方便,我们新建一个winform项目,命名为MultiThreadDemo。

  

  首先创建一个足以让你的程序卡住的方法函数:

   private void Display()

{

while (true)

textBox1.Text = new Random().NextDouble().ToString();

}

  然后添加一个对button1的调用,发现确实够用了。谁让你把死循环留给主线程去做,自己画图和数数,没时间给你答复。

  using System.Threading;

  然后在button1中添加代码并为他创建一个线程。让我们将此线程命名为“UiThread”以进行特殊处理和显示。

  

  

  查看代码

   private void button1_Click(object sender, EventArgs e)

{

Thread thread = new Thread(Display);//创建一个线程

thread.Start();

// Display();

}

  如果你急着跑,肯定会回来骂我,何乐而不为,有没有提示:“线程间操作无效:创建控件“textBox1”的线程从不访问它。”。因为主线程和你创建的线程是两个不相关的线程,那么两个陌生人怎么处理呢?也就是你的UiThread在未经主线程同意的情况下调用textBox1,别人会让你这么做吗?

  所以为了处理他们工作不协调的问题,故意强行取消线程警告。在构造函数中加一句:

   public Form1()

{

InitializeComponent();

Control.CheckForIllegalCrossThreadCalls = false;//加上这句就不会警告了

}

  这样一个简单的多线程程序就诞生了。但有时有很多代码需要使用委托,而你又不想创建单独的函数,可以这样做:

  

  

  查看代码

  private void button1_Click(object sender, EventArgs e)

{

ThreadStart threadStart = new ThreadStart(delegate { Display(); });//创建一个委托,这样可以调用任意参数的函数了,甚至是零星的代码都可以

Thread thread = new Thread(threadStart);

thread.Start();

}

  但是,不建议这样做,它不是线程安全的,并且很有可能导致程序崩溃。

  通过上面的练习,我们知道创建线程可以做更多的事情。同样的,如果我们再创建几个线程,我们不是会做更多的事情吗?有必要。

  接下来正式进入我们今天的话题:多线程采集

  要多线程采集,首先解决单个下载。

  using System.Net;

using System.IO;

  

  查看代码

   ///

/// 转载请加上本人博客链接

///

///

///

static void Request(RichTextBox richtextBox,int i)

{

richtextBox.AppendText(string.Format("线程{0}开始接收\n", Thread.CurrentThread.Name));

ServicePointManager.DefaultConnectionLimit = 1000;

HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(string.Format("http://news.cnblogs.com/n/{0}/", (int)i));//这里的i最嗨是158100到158999,符合博客园url规则才能采集到

StreamWriter sw = File.CreateText(string.Format(Environment.CurrentDirectory + "\\{0}.htm", i));

try

{

HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();

Stream stream = httpWebResponse.GetResponseStream();

StreamReader sr = new StreamReader(stream);

string html = sr.ReadToEnd();

richtextBox.AppendText(string.Format(Thread.CurrentThread.Name + "接收完毕"));

sw.Write(html);

sw.Close();

}

catch

{

richtextBox.AppendText(string.Format("线程{0}不存在此地址,跳过\n", Thread.CurrentThread.Name));

sw.Write(string.Format("线程{0}不存在此地址,跳过\n", Thread.CurrentThread.Name));

return;

}

}

  然后调用button2

  

  

  查看代码

   private void button2_Click(object sender, EventArgs e)

{

ThreadStart threadStart = new ThreadStart(delegate { Request(richTextBox1, 158100); });//创建一个委托,这样可以调用任意参数的函数了,甚至是零星的代码都可以

Thread thread = new Thread(threadStart);

thread.Start();

}

  这样,一个采集就完成了。

  想要像优采云采集那样,以现在的水平自然是做不到的。至少应该制作批次 采集。无非是使用多线程。

  

  

  查看代码

   ///

/// 转载请加上本人博客链接

///

///

///

static void Request(RichTextBox richtextBox,int i)

{

richtextBox.AppendText(string.Format("线程{0}开始接收\n", Thread.CurrentThread.Name));

ServicePointManager.DefaultConnectionLimit = 1000;

HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(string.Format("http://news.cnblogs.com/n/{0}/", (int)i));//这里的i最嗨是158100到158999,符合博客园url规则才能采集到

try

{

HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();

Stream stream = httpWebResponse.GetResponseStream();

StreamReader sr = new StreamReader(stream);

string html = sr.ReadToEnd();

richtextBox.AppendText(string.Format(Thread.CurrentThread.Name + "接收完毕\n"));

StreamWriter sw = File.CreateText(string.Format(Environment.CurrentDirectory + "\\{0}.htm", i));

sw.Write(html);

sw.Close();

}

catch

{

richtextBox.AppendText(string.Format("线程{0}不存在此地址,跳过\n", Thread.CurrentThread.Name));

}

}

private void button2_Click(object sender, EventArgs e)

{

Thread.CurrentThread.Name = "主线程";

Thread[] threads = new Thread[51];

DateTime endTime = DateTime.Now;

DateTime startTime = DateTime.Now;

TimeSpan timeSpan = endTime - startTime;

string span = timeSpan.TotalSeconds.ToString();

startTime = DateTime.Now;

Mutex mt = new Mutex();

mt.WaitOne();

for (int i = 158300; i >158250; i--)

{

threads[158300 - i] = new Thread(new ParameterizedThreadStart(delegate { Request(richTextBox1, i); }));

threads[158300 - i].Name = "线程" + (i).ToString(); ;

threads[158300 - i].Start();

}

mt.ReleaseMutex();

endTime = DateTime.Now;

timeSpan = endTime - startTime;

span = timeSpan.TotalSeconds.ToString();

richTextBox1.AppendText(string.Format("多线程接受的话共花费了{0}秒钟\n", span));

}

  多线程 采集 已完成。其实这篇文章主要关注的是创建线程的话题。技术含量很低。给刚入门的朋友练习一下吧!

  

  教程每天都会更新,请继续关注。

  ///****************************************************** ***** ******

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线