多线程
public Form1()
{
InitializeComponent();
//每一个应用程序都是一个进程
//每个进程有一个以上的线程组成
获取当前电脑所有的进程
//Process[] pro = Process.GetProcesses();
循环输出所有的进程信息
//foreach (var item in pro)
//{
// //杀死所有进程
// //item.Kill();//会蓝屏的
// Console.WriteLine(item);
//}
获取当前正在运行的系统的进程信息
//Process curr = Process.GetCurrentProcess();
//Console.WriteLine(curr);
关闭该进程
curr.Kill();
//Process.Start("calc");//启动计算器
//Process.Start("mspaint");//启动画图
//Process.Start("iexplore", "http://www.baidi.com");//启动IE
//Process.Start("firefox", "http://www.baidi.com");//启动IE
//Process.Start("devern");//启动vs
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 单线程直接调用打印输出方法Test
/// 因为该方法会耗费大量的时间
/// 在该方法执行完成之前进程都会在处理该方法
/// 从而导致程序出现假死现象,导致程序无法进行其他的任何操作
///
/// 程序在启动之后会产生一个主线程,在没有调用Test方法前,主线程来可以来处理窗体拖动,最大化,最小化等操作
/// 但是一旦Test开始执行,则主线程就用来处理Test方法内的操作
/// 而此时拖动窗体的时候就需要等主线程执行完Test方法之后空闲下来才可以执行拖动窗体操作
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
//单线程直接调用Test方法
Test();
}
/// <summary>
/// 多线程调用Test方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
//创建一个线程去调用Test方法
Thread th = new Thread(Test);
//指定该线程为后台线程,关闭前台主线程的时候会立刻关闭后台线程
//关闭界面的时候,就算改方法没有执行完成也会直接关闭掉不在继续执行
//如果不设置改参数,则创建的是前台线程
//如果这时直接关闭界面,如果该线程调用的方法没有执行完成,线程不会关闭会继续运行
//这是因为我们关闭窗体的时候只关闭了前台主线程,而我们创建的这个前台线程没有一起关闭
th.IsBackground = true;
//注意这里的Start,并不是直接就启动该线程
//而是告诉CPU,该线程已经准备好了,可以被调用了
//但是只有CPU空闲的时候才会开始调用,如果CPU很忙,就算是启动了多线程也不会立刻调用该线程
th.Start();
}
Thread thNew;
/// <summary>
/// 调用Test2方法,把结果输出到文本框中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
//让主线程睡3秒再执行下面的操作
Thread.Sleep(3000);
thNew = new Thread(Test2);
thNew.IsBackground = true;
thNew.Start();
}
/// <summary>
///
/// </summary>
private void Test()
{
for (int i = 0; i < 10000; i++)
{
Console.WriteLine(i.ToString());
}
}
/// <summary>
///
/// </summary>
private void Test2()
{
for (int i = 0; i < 10000; i++)
{
//如果直接赋值会报错
//应为文本框是在界面加载的时候由主线程创建的
//而调用该方法是在我们新创建的线程中操作的,这就出现了跨线程访问的问题
//如果不要让他检测是否跨线程操作的,则需要在构造函数或者load方法中设置Control.CheckForIllegalCrossThreadCalls = false;
textBox1.Text = i.ToString();
//ps:如果在Test2方法没有执行完的时候直接关闭界面,则可能会报【无法访问已释放的对象】
//这是因为文本框是主线程创建出来的,当关闭界面的时候主线程已经关闭,则其创建的文本框也会被释放而不再存在
//而这时我们创建的新线程却还在访问主线程创建的文本框对象
//这是后的文本框对象已经释放,所以才会因为找不到而报错
//要处理该报错,需要在关闭主线程的时候同时关闭我们创建的线程
//需要在Form1_FormClosing中处理
}
}
/// <summary>
/// 关闭窗体的时候关闭我们创建的后台线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//当我们关闭窗体的时候关闭我们创建的后台线程
if (thNew != null)
{
//使用Abort来终止线程并且释放线程所占用的资源
//而且线程一旦被关闭则不能再被起启动
thNew.Abort();
}
}
/// <summary>
/// 带参数的线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
Thread th = new Thread(Test3);
th.IsBackground = true;
th.Start("丽丽");
}
/// <summary>
/// 方法的参数类型只能是object,如果定义其他类型会报错
/// </summary>
/// <param name="obj"></param>
public void Test3(object obj)
{
string name = obj.ToString();
MessageBox.Show("我叫" + name);
}