1. Thread
Thread默认开启前台线程。 其他的开启方式默认开启后台线程。
-
首先导入命名空间:
System.Threading
-
实例化一个Thread对象
Thread newThread = new Thread(AMethod);
// AMethod,为该线程将要执行的任务。
- 启动线程
若要开始执行线程,可使用Start
方法
newThread.Start();
- 停止线程
newThread.Abort();
Thread
线程的多种常用方法列表
方法 | 操作 | 雷潮 |
---|---|---|
Start | 使线程开始运行 | |
Sleep | 使线程暂停指定的一段时间。 | |
Suspend | 在线程到达安全点时,使其暂停。 | |
Abort | 在线程到达安全点时,使其停止。 | |
Resume | 重新启动挂起的线程 | |
Join | 使当前线程一直等到另一线程完成。 在与超时值一起使用时,如果该线程在分配的时间内完成,此方法将返回 True。 |
安全点:
安全点是指代码中公共语言运行时可以安全地执行自动“垃圾回收”的位置。垃圾回收是指释放不再使用的变量并回收内存的过程。 调用线程的 Abort 或 Suspend 方法时,公共语言运行时将对代码进行分析,确定让线程停止运行的适当位置。
属性 | 值 | 雷潮 |
---|---|---|
IsAlive | 如果线程处于活动状态,则包含值 True。 | |
IsBackground | 获取或设置一个布尔值,该值表示一个线程是否是,或是否应当是后台线程。 后台线程与前台线程类似,但后台线程不阻止进程停止。 一旦某个进程的所有前台线程都停止,公共语言运行时就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。 | |
Name | 获取或设置线程的名称。 通常用于在调试时发现各个线程。 | |
Priority | 获取或设置操作系统用于确定线程调度优先顺序的值。 | |
ApartmentState | 获取或设置用于特定线程的线程模型。 线程模型在线程调用非托管代码时很重要。 | |
ThreadState | 包含描述线程状态的值。 |
Thread
的相关属性:
属性 | 值 | 雷潮 |
---|---|---|
IsAlive | 如果线程处于活动状态,则包含值 True。 | |
IsBackground | 获取或设置一个布尔值,该值表示一个线程是否是,或是否应当是后台线程。 后台线程与前台线程类似,但后台线程不阻止进程停止。 一旦某个进程的所有前台线程都停止,公共语言运行时就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。 | |
Name | 获取或设置线程的名称。 通常用于在调试时发现各个线程。 | |
Priority | 获取或设置操作系统用于确定线程调度优先顺序的值。 | |
ApartmentState | 获取或设置用于特定线程的线程模型。 线程模型在线程调用非托管代码时很重要。 | |
ThreadState | 包含描述线程状态的值。 |
线程优先级
每个线程都有一个优先级属性,用于确定其执行所占用的处理器时间片大小。 操作系统为高优先级线程分配较长的时间段,并为低优先级线程分配较短的时间段。 新创建的线程具有值Normal
,但可以将 Priority 属性更改为 ThreadPriority
枚举中的任何值。
2. 通过委托来开启线程
通过委托,调用BeginInvoke
方法来开启一条线程,去执行该委托所指向的方法。
// 线程执行该方法
static string test1(int x, int y)
{
Console.WriteLine(x + y);
return x + "+"+ y;
}
static void Main(string[] args)
{
Func<int, int, string> fun1 = test1;
// 通过委托来开启线程执行。 倒数第二个参数是,线程执行完毕之后的回调方法, 倒数第一个参数是,执行完之后,携带的参数。
fun1.BeginInvoke(10, 20, test1CallBack, fun1);
}
// 通过委托来传递回调函数,会自动将该线程的执行结果 传递过来
static void test1CallBack(IAsyncResult ar)
{
//AsyncState 获取所携带的参数,在这里就是上面fun1.BeginInvoke(10, 20, test1CallBack, fun1); 这行代码中,所传递的fun1
Func<int, int, string> fun1 = ar.AsyncState as Func<int, int, string>;
// 获取委托所指向的方法的执行结果。
string result = fun1.EndInvoke(ar);
Console.WriteLine("这就是结果" + result);
}
// 模拟多线程场景
static void Main(string[] args)
{
// 利用委托,注册下载图片方法
Func<int, int, string> f = DownLoadVideo;
//f(10, 20);
// 开启线程,并执行下载方法,下载完毕后,执行DownLoadIsOk方法
f.BeginInvoke(10, 20,DownLoadIsOk,f);
Console.ReadKey();
}
private static void DownLoadIsOk(IAsyncResult ar)
{
Console.WriteLine("视频已下载完毕");
Console.WriteLine(ar.AsyncState);
}
private static string DownLoadVideo(int arg1, int arg2)
{
Console.WriteLine("正在下载视频");
return arg1 + "" + arg2;
}
3. 线程池
static void ThreadFunc3()
{
Console.WriteLine("--------");
// 调用线程池来执行任务。 每调用一次,就会开启一条线程来执行该任务。
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
ThreadPool.QueueUserWorkItem(test3);
Console.WriteLine("========");
Thread.Sleep(100);
}
// 线程池调用的方法,需要一个object类型的参数方法,且不能有返回值
static void test3(object obj)
{
Thread.CurrentThread.IsBackground = false;
Console.WriteLine("asdas");
}
4. Task 开启
static void ThreadMethod()
{
Console.WriteLine("ThreadMethod Begin" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("Thread End");
}
static void continueTask(Task t)
{
Console.WriteLine("task is continue" + t.Id);
Thread.Sleep(3000);
Console.WriteLine("task is complete");
}
static void Main(string[] args)
{
// 第一种方式开启
//Task t = new Task(ThreadMethod);
//t.Start();
//// 第二种方式开启
//TaskFactory tf = new TaskFactory();
//tf.StartNew(ThreadMethod);
Task t1 = new Task(ThreadMethod);
Task t2 = t1.ContinueWith(continueTask);
t1.Start(); // 开启任务 t1, 当t1执行完毕的时候,会执行t2的任务
Console.ReadKey();
}
5. 线程使用问题
- 1、资源竞争
多个线程访问同一个资源,对同一个资源做修改,会引发数据混乱。 - 2、死锁
多把锁。互相牵制。导致线程都互相等待解锁。 - 3、案例:
- 4、银行存取款
- 5、多窗口同时卖票
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace TestProject
{
class SaleTicket
{
private Thread thread1;
private Thread thread2;
private Thread thread3;
private int ticketCount = 1000;
public SaleTicket()
{
thread1 = new Thread(Sale);
thread2 = new Thread(Sale);
thread3 = new Thread(Sale);
}
public void Sale()
{
while(true)
{
lock(this)
{
if (ticketCount > 0)
{
ticketCount -= 1;
Console.WriteLine(Thread.CurrentThread.Name + "卖了一张票,剩余" + ticketCount);
}
else
{
Console.WriteLine(Thread.CurrentThread.Name + ":票卖完了");
break;
}
}
}
}
public void StartSaleTicket()
{
thread1.Start();
thread2.Start();
thread3.Start();
}
}
}
作者:silence_k
链接:http://www.jianshu.com/p/00b33e5cd149
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论