操作系统为了提高效率将一个进程分成多个线程。有一个主线程其他的都为子线程,在认识多线程前,我们的代码都是在主线程中执行的。都有一个规则就是 必须执行当前代码才会执行之后的代码。那么问题就来了,假如说有一个非常耗时的操作,比如加载数据或文件下载,难不成数据加载完之前,之后的代码以及其他代码都不执行吗?我们用过不少软件,比如迅雷、百度云,在下载文件的时候还可以进行其他操作,程序不会因为当前任务没执行完而停止。这就运用到了线程。如果将一个耗时10秒的操作放到主线程中,当程序执行到这段代码的时候就会卡机,也就是程序未响应。一种方法是用户等待10秒后让程序执行完,但大多数用户会选择后者:关闭程序。
一、Thread 类:(System.Threading.Thread)
表示托管线程,运行在.NET平台之上的,每一个Thread对象代表一个线程,多线程开发就有多个Thread对象。每一个线程都对应着一个任务(方法)。
二、示例代码;该窗体有3个控件一个label,两个button
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Csharp窗体练习
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private int count = 0;
private void btnCounter_Click(object sender, EventArgs e)
{
Thread objThread = new Thread(delegate()
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(1000);
if (label1.InvokeRequired)
{
label1.Invoke(new Action
((s,num) => { label1.Text = s+num; }) , count.ToString(),i);
}
}
});
objThread.IsBackground = true;
objThread.Start();
count++;
}
private void btnClear_Click(object sender, EventArgs e)
{
count=0;
}
}
}
首先第一步是创建Thread 对象: Thread objThread=new Thread(<参数>);Thread构造方法中有参数,可以选中Thread按F1查看帮助文档.翻开这些参数的定义:
public delegate void ParameterizedThreadStart( object obj )
ParameterizedThreadStart其实就是一个无返回值带参数的一个委托。
public delegate void ThreadStart()
当然这就是一个无参数的委托。总结起来就是Thread构造方法里要放一个委托...所以上述使用了匿名方法当然也可以使用lambda表达式在匿名方法里写要操作的内容。
之后别忘了把线程IsBackground 属性设为true,默认为前台线程,设为true时为后台线程。前台线程与后台线程的区别是,应用程序必须在所有前台线程完成后才关闭,而后台线程,应用程序可以不考虑后台线程是否执行完,应用程序关闭后台线程自动关闭。如果你关闭了某个应用程序,但是在进程中发现该应用程序还在运行,说明该程序的前台进程还在运行。要么是编程的时候不注意,也有可能是流氓软件。
最后把线程start就可以了。
但是,在子线程中无法直接访问主线程的可视化控件,主线程和子线程就像各部门一样,做自己的事情,但是想随意访问内部消息是不允许的。虽然不能直接访问但是能间接访问呐,便可以使用Invoke()方法来实现。 Invoke(<delegate method>,object args[]) ,第一个参数是通过委托调用的方法,之后的参数都是传给这委托的参数的值。在此之前判断InvokeRequired 是否必须调用Invoke方法。
Invoke方法第一个参数我用了Action。Action和Func都内置了委托,Action为无返回值的匿名方法,而Func有返回值 Func<参数1,参数2...,参数n,返回值>,除最后一个是返回值,之前的都是要传给方法的参数.