关于多线程处理,根据自己的学习做了一下总结,算是复习用,下面主要贴一些实例Demo。看此博客建议先将.Net委托(拉姆达表达式)先学习一下,否则,看起来可能比较吃力,至少我是这样的。
为了清晰,我把标题做了红字黄底加粗显示。
1,启动线程调用无参无返回值的方法
Console.WriteLine("主线程开始");
Thread t1 = new Thread(new ThreadStart(Test1));//可以通过IsBackground=true,把指定线程设置为后台线程。//默认创建的进程都是“前台线程”,只有当所有“前台线程”都执行完毕后“进程”才会结束。//后台线程在所有前台线程执行完毕后,自动退出。t1.IsBackground = true;t1.Start();//在哪个线程中执行,就阻塞了哪个线程,那个线程要等待t1线程执行完毕后,然后才会继续。//如果不理解,把t1.Join()注掉观察结果//Join可以在在参数中设置阻塞时间,例如t1.Join(1000)t1.Join();Console.WriteLine("主线程结束");Console.Read();2,启动线程调用有参数无返回值的方法
①利用预定义的函数调用
Console.WriteLine("主线程开始");
Thread t2 = new Thread(new ParameterizedThreadStart(Test2));t2.Start(100);Console.WriteLine("主线程结束");Console.Read();②将函数封装到类中,演变成调用无参数无返回值的方法
MyClass mc = new MyClass();
mc.Num = 100;Thread t3 = new Thread(new ThreadStart(mc.Test3));t3.Start();Console.Read();class MyClass
{
private int num;
public int Num
{
get { return num; }
set { num = value; }
}
public void Test3()
{
int result = 0;
for (int i = 0; i < this.Num; i++)
{
result += i;
}
Console.WriteLine(result);
}
}
3,启动线程调用有参数有返回值得方法
①BackgroundWorker实现
BackgroundWorker backWorker = new BackgroundWorker();
backWorker.DoWork += backWorker_DoWork;backWorker.RunWorkerCompleted += backWorker_RunWorkerCompleted;backWorker.RunWorkerAsync(new int[] { 100 });Console.Read();static void backWorker_DoWork(object sender, DoWorkEventArgs e)
{ if (e.Argument != null) { int[] arr = e.Argument as int[]; e.Result = Test4(arr[0]); }}private static void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{ Console.WriteLine(e.Result);}
②异步委托调用实现
A,BeginInvoke&EndInvke的方式实现
Console.WriteLine("主线程开始");
MyDel md = new MyDel(Test4);IAsyncResult asyResult = md.BeginInvoke(100, null, null);for (int i = 0; i < 10; i++){ Console.WriteLine("主线程进行中..." + i);}//调用EndInvoke会阻塞线程,等待异步委托执行完毕。int sum = md.EndInvoke(asyResult);Console.WriteLine(sum);Console.WriteLine("主线程结束");Console.Read();B,回调的方式实现
MyDel md = new MyDel(Test4);
IAsyncResult asyResult = md.BeginInvoke(100, CallBack, "Test");Console.WriteLine("主线程继续");Console.Read();private static void CallBack(IAsyncResult res)
{ Console.WriteLine("回调函数执行中"); AsyncResult ar = res as AsyncResult; int sum = ((MyDel)ar.AsyncDelegate).EndInvoke(ar); Console.WriteLine("返回值是:"+sum);}4,终止线程
if (t1 != null)
{ t1.Abort();}5,跨线程访问控件
如果不关闭跨线程访问控件检查,会抛出异常
//Thread t2 = new Thread(new ThreadStart(() =>//{ // this.textBox1.Text = "Hi";//}));//t2.IsBackground = true;//t2.Start();Thread t1 = new Thread(new ThreadStart(() =>{ //利用控件的Invoke方法,将控件的操作放到创建空间的线程中进行 this.textBox1.Invoke(new Action<string>(UpdateText), "hello");}));t1.IsBackground = true;t1.Start();6,线程池
Console.WriteLine("Main thread ID:" + Thread.CurrentThread.ManagedThreadId);
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>{ Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 10; i++) { Console.WriteLine("."); Thread.Sleep(500); }}));ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>{ Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 10; i++) { Console.WriteLine("*"); Thread.Sleep(500); }}));ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>{ Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 10; i++) { Console.WriteLine("="); Thread.Sleep(500); }}));Console.WriteLine("主线程继续");Console.Read();7,锁机制
static long max = 100000;
static long idx = 0;static readonly object objSync = new object();static void Main(string[] args){ Thread t1 = new Thread(new ThreadStart(() => { for (int i = 0; i < max; i++) { lock (objSync) { idx++; } } })); t1.IsBackground = true; t1.Start(); for (int i = 0; i < max; i++) { lock(objSync) { idx--; } } t1.Join(); Console.WriteLine("最终idx="+idx); Console.Read();8,单线程造成界面假死多线程解决
Random rd = new Random();
单线程,线程一直在做死循环,无法更新界面
//while (true)
//{
// label1.Text = rd.Next(0, 10).ToString();
// label2.Text = rd.Next(0, 10).ToString();
// label3.Text = rd.Next(0, 10).ToString();
// Thread.Sleep(300);
//}
//开启一个线程专门处理界面显示
t1 = new Thread(new ThreadStart(() =>
{
while (true)
{
label1.Text = rd.Next(0, 10).ToString();
label2.Text = rd.Next(0, 10).ToString();
label3.Text = rd.Next(0, 10).ToString();
Thread.Sleep(300);
}
}));
t1.IsBackground = true;
t1.Start();