c#的線程的創建有兩種方式,一種是使用無參的ThreadStart,另外一種是傳參的ParameterizedThreadStart(只允許傳遞一個參數,但可以將對象作為參數傳遞,所以使用上也是非常簡單)
static void Main(string[] args)
{
//MyList mylist = new MyList();
//mylist.dict();
SaleData sale = new SaleData(100);
checkproduce checkproduce = new checkproduce();
//註冊檢查函數
sale.checkData += new SaleData.checkNum(checkproduce.check);
ThreadStart threadStart = new ThreadStart(sale.saleDone);
Thread thread = new Thread(threadStart);
thread.Start();
Console.WriteLine("業務執行完畢");
//此處需要傳遞一個靜態函數
Thread t = new Thread(new ParameterizedThreadStart(Add));
//將對象直接傳遞過去
t.Start(sale);
Console.ReadKey();
}
static void Add(object data)
{
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static myjob.EventTest;
namespace myjob
{
//訂閱器
public class checkproduce {
//檢查庫存值
public void check()
{
Console.WriteLine("觸發庫存檢查函數,庫存減少 ");
Thread.Sleep(1000);
Console.WriteLine("庫存檢查完畢");
}
}
//銷售數據校對
public class SaleData {
public int sale_num=10;
public delegate void checkNum();
public event checkNum checkData;
public SaleData(int num)
{
sale_num = num;
}
public void saleDone()
{
Console.WriteLine("啟動新的子線程");
checkData();
}
public static void saleNum(SaleData saleData)
{
Console.WriteLine("銷售" + saleData.sale_num);
}
}
}
c#中把線程的狀態分為終止狀態(運行),非終止狀態(被阻塞)兩種狀態。為了更好地管理現成的狀態,使用兩個工具類AutoResetEvent和ManualResetEvent進行管理。
autoresetevent設置為false,waitone需要等待信號,為true時候不會阻塞
public class ThreadDemo
{
public static AutoResetEvent threadPayMoneyOne = new AutoResetEvent(false);
public void wake()
{
Console.WriteLine("線程啟動");
threadPayMoneyOne.WaitOne();
Thread.Sleep(3000);
Console.WriteLine("執行完畢");
}
static void Main(string[] args) {
ThreadDemo threadDemos = new ThreadDemo();
Thread thread = new Thread(new ThreadStart(threadDemos.wake));
thread.Start();
//喚醒子線程
//ThreadDemo.threadPayMoneyOne.Set();
Console.WriteLine("繼續執行業務");
Console.ReadKey();
}
ManualResetEvent 调用一次Set()后将允许恢复所有被阻塞线程。需手动在调用WaitOne()之后调用 Reset()重置信号量状态为非终止,然后再次调用WaitOne()的时候才能继续阻塞线程,反之则不阻塞
public class ThreadDemo2
{ //
public static ManualResetEvent threadtwo = new ManualResetEvent(false);
public static void wake()
{
Console.WriteLine("線程啟動");
threadtwo.WaitOne();
Thread.Sleep(3000);
Console.WriteLine("執行完畢");
Console.WriteLine("————————————");
}
}
1.ManualResetEvent 调用一次Set()后将允许恢复所有被阻塞线程。需手动在调用WaitOne()之后调用Reset()重置信号量状态为非终止,然后再次调用WaitOne()的时候才能继续阻塞线程,反之则不阻塞
2.AutoResetEvent,调用一次Set()只能继续被阻塞的一个线程,多次调用Set()才行,但不需手动调用Reset();再次调用WaitOne()的时候又能阻塞线程,也是和前者的区别
3.两者单个实例均可阻塞一个或多个线程,在多个线程中调用 主线程 创建的 两者单个实例.WaitOne(),前提是两者实例必须是非终止状态
4.两者实例化构造参数解释
true:设置终止状态。相当于调用了Set(),即首次不会被WaitOne()阻塞,下次执行WaitOne()才会被阻 塞
false:设置非终止状态。遇到WaitOne()立即阻塞所在的一个或多个线程
5.两者都只会阻塞WaitOne()所在的线程,WaitOne()可被多个线程调用
為了更好地進行異步任務的管理,c#使用Task類,可以非常輕鬆實現任務的編排,定時停止等需求。
task的創建有三種方式,一種是使用action傳遞參數,一種使用lmada表達式創建,和最後的 Task.Factory.。task任務需要使用start方法啟動,wait方法設置任務的啟動。
static void Main(string[] args)
{
Action
處理超時任務,只需要在wait添加超時參數,一旦超時,直接關閉後台任務
static void Main(string[] args)
{
Task task2 = Task.Run(() =>
{
CallBack callBack = new CallBack();
callBack.download();
});
//設置超時直接停止任務
task2.Wait(1000);
Console.WriteLine("任務運行狀態為 {0}", task2.Status);
}
//task2停止才能開始執行task1
Task task2 = Task.Run(() =>
{
CallBack callBack = new CallBack();
callBack.download();
});
//設置超時直接停止任務
task2.Wait(500);
while (true)
{
Console.WriteLine("任務運行狀態為 {0}", task2.Status);
if (task2.IsCompleted == true)
{
Task task1 = Task.Run(() =>
{
CallBack callBack = new CallBack();
callBack.download();
Console.WriteLine("任務一停止");
});
task1.Wait();
break;
}
}
當不需要指定等待的任務時候,可以選擇使用waitany和waitall語法,這兩者的區別在於waitany只等待一個任務,而waitall是等待任務組全部執行完成。
//多任務編排 不會阻塞主線程
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => {
Thread.Sleep(200);
Console.WriteLine("任務池任務結束");
});
}
Task.WaitAll(tasks);
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
Console.WriteLine("任務池結束");