额,我猜你现在可能会这么想“既然线程会对我的程序产生负面影响,那么我为什么要使用它呢?”。其实问题的关键不在于到底用不用线程,而在于何时何地使用线程。知道在什么情况下应该使用线程是好的设计决策的核心。使用线程有两个不同的优势。在这一部分,我们将讨论这两个优势是什么。

后台处理逻辑

第一个使用线程的优势是当你需要在后台运行一个很耗时的操作同时希望用户界面仍然可用时。我们都遇到过很多次由于后台在查询数据或者在处理大量信息而导致界面没有响应的情况。例如,专业图形处理软件以一个特定格式显示图片时。在一些产品的早期版本,让程序显示一个大的图片会导致程序没有响应直到图片显示出来。有时候为了完成某项工作,我们不得不让它晚上来处理图片,然后第二天早上来看我们期望的结果,这样做也是由于在电脑面前空坐一个小时忒不靠谱。这个问题在于提供一个后台线程来做一些CPU敏感工作同时让你的用户界面运行在主线程中。

我们来看一个需要生成新线程来处理的后台操作。这个例子主要是用来做文件搜索的。当搜索引擎找到一个匹配的文件后,它会向列表中添加一个新值。

下面的代码显示这个方法确实需要生成新线程:

/*************************************
/* Copyright (c) 2012 Daniel Dong* * Author:oDaniel Dong* Blog:o  www.cnblogs.com/danielWise* Email:o guofoo@163.com* */using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;namespace SearchForm
{public partial class Form1 : Form{string search;string[] args = new string[1];delegate void UpdateData(string returnVal);UpdateData UIDel;public Form1(){InitializeComponent();}private void cmdSingle_Click(object sender, EventArgs e){Search();}public void Search(){search = textBox1.Text;SearchDirectory(@"D:\Pictures");}public void SearchDirectory(string path){//Search the directoryDirectoryInfo di = new DirectoryInfo(path);FileInfo[] fi = di.GetFiles(search);foreach (FileInfo myFile in fi){args[0] = myFile.FullName;
                if (UIDel != null){this.Invoke(UIDel, args);}else{UpdateUI(args[0]);}}//Search its sub directories.DirectoryInfo[] subDirs = di.GetDirectories();foreach (DirectoryInfo myDir in subDirs){SearchDirectory(myDir.FullName);}}private void cmdMultiple_Click(object sender, EventArgs e){UIDel = new UpdateData(UpdateUI);Thread t = new Thread(new ThreadStart(Search));t.Start();}private void UpdateUI(string result){lstPrime.Items.Add(result);}}
}

编译上面的例子然后运行。在搜索框输入一个搜索条件,比如*.*, 单击单线程搜索按钮,然后观察结果。你会发现,我们在搜索文件同时试着在每次发现匹配的文件时向界面更新一次。然而,由于用户界面和搜索程序代码运行在同一个线程中,我们在搜索代码完成之前看不到任何更新。我们也无法在搜索过程中重新设定窗体尺寸大小。

这个很长的代码片段实际上是一个非常简单的场景。我们来看一下能否通过一个简单的的改动来解决这个问题。在多线程搜索按钮中添加下面代码并使用一个新线程来搜索:

private void cmdMultiple_Click(object sender, EventArgs e)
{UIDel = new UpdateData(UpdateUI);Thread t = new Thread(new ThreadStart(Search));t.Start();
}

我们再次编译运行上面的例子。输入同样的搜索条件然后单击多线程搜索按钮。你可以看到有一些不同的地方-这次我们的输出结果会立即显示出来。这是因为Windows现在会在后台搜索线程和前台显示线程之间进行切换。处理器现在给了界面显示程序独立执行时间。你也会发现在搜索过程中可以重新设定窗体大小。

也可能有其他导致我们的用户接口没有响应的后台程序。我们可能还有一些更消耗CPU 资源的处理过程,比如对数据库执行搜索,排序,格式化,截取以及过滤数据功能。这是使用多线程的另外一种情况。你也可能生成一个单独线程进行日志处理。在这些情况下用户接口不会卡死,但是如果不是在它自己线程(进行日志操作)里的话会显得稍微有点慢。

访问外部资源

第二种可能要用到线程的情况是当你需要访问一些非本地的资源时。可能是网络上的一个数据库文件或者是网络共享文件之类的。在这种情况下,网络性能会极大地影响你的程序的性能。

让我们来看一个例子。在这个例子中我们将连接一个数据库。假设网络性能很差导致我们的程序性能也很不好。同时也假定公司安全策略规定在远程数据库服务器上不可以安装任何应用程序。

/*************************************
/* Copyright (c) 2012 Daniel Dong* * Author:Daniel Dong* Blog:  www.cnblogs.com/danielWise* Email: guofoo@163.com* */using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Threading;namespace Chapter02
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void cmdQuery_Click(object sender, EventArgs e){QueryData();}public void QueryData(){SqlDataReader objReader;SqlConnection objConn;SqlCommand objCommand;int intEmployeeID;string strFirstName;string strTitle;int intReportsTo;objConn = new SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True");objCommand = new SqlCommand("SELECT EmployeeID, FirstName, Title, ReportsTo FROM Employees", objConn);objConn.Open();objReader = objCommand.ExecuteReader(CommandBehavior.CloseConnection);while (objReader.Read()){intEmployeeID = objReader.GetInt32(0);strFirstName = objReader.GetString(1);strTitle = objReader.GetString(2);if (objReader.IsDBNull(3)){intReportsTo = 0;}else{intReportsTo = objReader.GetInt32(3);}listBox1.Items.Add(intEmployeeID.ToString() + " "+ strFirstName + " " + strTitle + " "+ intReportsTo.ToString());}objReader.Close();objConn.Close();}}
}
 

你可以从这个例子中发现我们所做的就是查询一个数据库(本例中为了方便使用本地数据库,实际应用时一般是远程数据库)。返回的数据不是很多,但是你会发现用户界面会在它花费时间获取数据并更新到列表中得这段时间内卡住。我们仍然通过另外生成一个线程并在这个新的线程中执行数据库查询来改进这个程序。现在再添加一个新的按钮并加入以下代码:

private void cmdMultiQuery_Click(object sender, EventArgs e){Thread t = new Thread(new ThreadStart(QueryData));t.Start();}

现在我们运行这段代码,会得到与我们上个例子的结果类似的结果:

我们也可以在查询过程中重设窗口尺寸。用户界面在整个查询过程中都是相应的。当然,我想重申的是以上内容并不意味着你应该在每次访问数据库时都创建一个新线程。你应该先分析一下能否把数据库文件或者程序移动到同一台服务器上。同时确定这个组件不会被不同的客户端程序持续地调用。如果是这样的话那么就得为每次调用生成一个新线程且会比你期望的消耗更多资源。当每次调用我们的对象时不用都生成新线程,有些时候可以重用对象以及线程。这个问题将会在第三章和第五章介绍。

下一篇介绍线程陷阱以及循环中的线程...

转载于:https://www.cnblogs.com/danielWise/archive/2012/01/17/2325008.html

C# 线程手册 第二章 .NET 中的线程 线程的优势相关推荐

  1. 计算机和学数制和码制,[文学]第二章 计算机中的数制和码制.ppt

    [文学]第二章 计算机中的数制和码制 注意:十六进制计数法是为了克服二进制计数法书写麻烦而引入的一种进位计数制:在编写汇编语言源程序时,如果一个十六进制数的最高位为A?F中的一个数字符号时,该数前面必 ...

  2. 世界上第一台数字计算机图片大全,第二章 计算机中的图世界

    <第二章 计算机中的图世界>由会员分享,可在线阅读,更多相关<第二章 计算机中的图世界(13页珍藏版)>请在人人文库网上搜索. 1.第二章第二章 计算机中的图世界计算机中的图世 ...

  3. (Java零基础学习笔记)第二章 Java中的基本语法

    前言: 大家好! 我是BA unravel .如果你想和我一起学习JAVA,欢迎大家一起来学习这个世界上最好的语言! 学习目标: 一周掌握 Java 入门知识 学习内容: 1. 搭建 Java 开发环 ...

  4. 半导体物理第二章 半导体中的杂质和缺陷能级

    半导体物理第二章 半导体中的杂质和缺陷能级 为什么要研究杂质和缺陷能级啊?第一是因为这事客观存在的:因为现实中有一些偏离理想的复杂情况,首先,原子自己不是静止的,不是在严格的周期性晶格的格点位置就不动 ...

  5. C# 线程手册 第一章 线程定义 .NET 和 C# 对线程的支持

    由于.NET Framework 支持自由线程,所以自由线程在所有.NET 语言中都存在,包括C#和VB.NET. 在下一部分,我们将着重关注如何提供这种支持以及更多关于线程是如何做到的,而不再关注线 ...

  6. 管理系统中计算机应用第二章,管理系统中计算机应用第二章.doc

    管理系统中计算机应用第二章.doc 第二章 企业管理的信息化平台 一.单项选择题(本大题共30小题,每小题1分,共30分) 1.从理论上分析,传统的IP地址(IPv4)最多可以访问的用户数是( ) A ...

  7. Android 渗透测试学习手册 第二章 准备实验环境

    第二章 准备实验环境 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在上一章中,我们了解了 Android 安全性及其体系结构的基础知识. 在本章中,我们将了解如何 ...

  8. Caché程序员必须知道符号与缩写 第二章 ObjectScript中使用的缩写

    Caché程序员必须知道符号与缩写 第二章 Caché ObjectScript中使用的缩写 ObjectScript中可用的命令.函数和特殊变量的缩写表. 以下是ObjectScript中使用的名称 ...

  9. R700指令集架构参考手册第二章——2.5 程序状态

    表2.5到表2.8概括了可被一个在一个R700程序中的单个线程所访问的R700程序状态的程序员的视点. 表不包括: 1.由R700硬件专门维护的状态,诸如内部循环控制寄存器 2.仅对主机软件可访问的状 ...

最新文章

  1. 用NanoPi neo制作网络音箱了解一下?
  2. 免费的容器架构可视化工具 | 阿里云应用高可用服务 AHAS 发布重大新特性
  3. 2019-03-11-算法-进化(求众数)
  4. html选中列表整列变色,excel选中行变色完整代码和动画效果
  5. LeetCode 61. Rotate List
  6. 通过官方查看springCloud,springBoot版本对应关系
  7. sql between包括两端吗_sql:简单查询
  8. python支持函数式编程吗_利用Fn.py库在Python中进行函数式编程
  9. 【LCS】POJ1458Common Subsequence
  10. 自己的阿里云部署了django发现连不上, 一下是网上查的解决方法,亲测可用
  11. html js加载404_【第 245 期】2020 年,JS 令一个新人沮丧
  12. java 文件转换成二进制_java实现文件转换成二进制存储与取出
  13. 有限元基础及ANSYS应用 - 第4节 - 平面桁架结构的ANSYS分析
  14. Dapr for dotnet | 发布与订阅- Publish Subscribe
  15. 基于微信的旅游小程序、景区景点购票小程序、毕业设计、开题报告、毕业论文参考(1)小程序
  16. matlab用矩形法算积分,编写程序,使用矩形法、梯形法、辛普生法计算一重积分...
  17. 计蒜客 - A1503
  18. BI技巧丨目标达成(二)
  19. 排球计分规则3.17
  20. [转]微信终端跨平台组件 mars 系列(二) - 信令传输超时设计

热门文章

  1. java存储数据_Java 数据存储
  2. unity android so热更,惊鸿哥的港湾
  3. ionic ios查看大图报错 the file to show is not valid image,or could not be loaded
  4. 新蓝剑java_Ubuntu 8.10 编译安装飞鸽(IPMsg 0.9.6)
  5. php 静态 成员属性,[已解决]php中静态成员方法和静态成员变量是不是不支持多态?...
  6. 复习vue笔记第一天
  7. mysql innodb 事务_MySQL学习笔记之InnoDB事务实现
  8. html 点击子元素,html如何点击子元素事件而不触发父元素的点击事件——阻止冒泡...
  9. ios php mysql实例_php – 从iOS应用程序将图像存储到MYSQL数据库中
  10. 64位 iee754_IEEE754浮点表示法详解