[c#] 多线程网路编程应用[多线程文章采集]

优采云 发布时间: 2020-08-09 15:08

  编程不能死记硬背,要靠多实践操作

  如今的网路越来越发达,分享一个文件是这么的简单。特别是有了电骡、迅雷这样的下载软件就愈加如虎添翼了,想从网上下载一个几个G大小的文件,真是不费吹灰之力。好,废话太多了,直接步入俺们明天的主题吧。

  要实现象迅雷一样的多线程下载,核心问题是要将多线程的概念以及如何实现的问题弄清。

  当然,本文技术浓度太低,大牛请直接绕路。

  多线程是相对单线程来说的,具体可以参考百度百科里的解释:

  每个程序运行都有一个最基本的主线程,用于处理界面书法,人机交互,后台处理等过程,因此假如是在单线程程序里操作注视历时的动作,主界面都会太卡,甚至是难以工作。因此不管您是不是喜欢,最好都别用主线程把一切事务夺得,否则很难给用户一个凉爽的顾客体验。

  那么在C#里怎么实现多线程呢?

  下面使我们实现一个最简单的多线程实例;

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

  

  先创建一个足够使你的程序卡住不动的方式函数:

   private void Display()

{

while (true)

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

}

  然后给button1添加调用,发现确实够卡吧,谁使你把那种死循环的事情交给主线程去做呢,一个人又作图,又要算数,哪还有时间给你答复。

  using System.Threading;

  接着补充一下button1上面的代码,给他创建一个线程,我们把这线程起名叫“UiThread”用于专门处理显示吧。

  

  

  View Code

   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;//加上这句就不会警告了

}

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

  

  

  View Code

  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;

  

  

  View Code

   ///

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

///

///

///

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里调用

  

  

  View Code

   private void button2_Click(object sender, EventArgs e)

{

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

Thread thread = new Thread(threadStart);

thread.Start();

}

  这样以来单次采集就完成了。

  要想象优采云一样采集,自然以目前的水平是做不到的。起码也要把批量采集做下来。无外乎使用多线程。

  

  

  View Code

   ///

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

///

///

///

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人工客服


线