.NET多線程執行函數


  前面幾篇文章一直在寫LINQ,這里為什么會出現多線程?原因是DebugLZQ在寫一個LINQ綜合Demo的時候遇到了多線程,便停下手來整理一下。關於多線程的文章,園子里很多很多,因此關於多線程理論性的東西,LZ就不去多說了,這篇博文主要是用最簡單的例子,總結下多線程調用函數的相關注意點,重點偏向應用和記憶。

1.多線程調用無參函數                                                                                   

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace 多線程
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主線程開始");
            Thread t = new Thread(new ThreadStart(ShowTime));//注意ThreadStart委托的定義形式
            t.Start();//線程開始,控制權返回Main線程
            Console.WriteLine("主線程繼續執行");
            //while (t.IsAlive == true) ;
            Thread.Sleep(1000);
            t.Abort();
            t.Join();//阻塞Main線程,直到t終止
            Console.WriteLine("--------------");
            Console.ReadKey();
        }
        static void ShowTime()
        {
            while (true)
            {
                Console.WriteLine(DateTime.Now.ToString());               
            }
        }
    }
}

注意ThreadStart委托的定義如下:

可見其對傳遞進來的函數要求是:返回值void,無參數。

2.多線程調用帶參函數(兩種方法)                                                               

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace 多線程2_帶參數
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main線程開始");
            Thread t = new Thread(new ParameterizedThreadStart(DoSomething));//注意ParameterizedThreadStart委托的定義形式
            t.Start(new string[]{"Hello","World"});
            Console.WriteLine("Main線程繼續執行");

            Thread.Sleep(1000);
            t.Abort();
            t.Join();//阻塞Main線程,直到t終止
            Console.ReadKey();
        }
        static void DoSomething(object  s)
        {
            string[] strs = s as string[];
            while (true)
            {
                Console.WriteLine("{0}--{1}",strs[0],strs[1]);
            }
        }
    }
}

注意ParameterizedThreadStart委托的定義如下:

可見其對傳入函數的要求是:返回值void,參數個數1,參數類型object

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace 多線程2_帶參數2
{   
    class Program
    {
        static void Main(string[] args)
        {
            Guest guest = new Guest() 
            {
             Name="Hello", Age=99
            };
            Thread t = new Thread(new ThreadStart(guest.DoSomething));//注意ThreadStart委托的定義形式
            t.Start();

            Thread.Sleep(1000);
            t.Abort();
            t.Join();//阻塞Main線程,直到t終止
            Console.ReadKey();
        }
    }
    //
    class Guest
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void DoSomething()
        {
            while (true)
            {
                Console.WriteLine("{0}--{1}", Name, Age);
            }
        }
    }
}

這個還是使用ThreadStart委托,對方法進行了一個封裝。

兩種方法,可隨意選擇,第一種貌似簡潔一點。

3.線程同步                                                                                              

線程同步的方法有很多很多種volatile、Lock、InterLock、Monitor、Mutex、ReadWriteLock...

這里用lock說明問題:在哪里同步,用什么同步,同步誰?

首先感受下不同步會出現的問題:

代碼就是下面的代碼去掉lock塊。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace 多線程3_同步2
{
    class Program
    {
        static object obj = new object();//同步用

        static int balance = 500;

        static void Main(string[] args)
        {
            Thread t1 = new Thread(new ThreadStart(Credit));
            t1.Start();

            Thread t2 = new Thread(new ThreadStart(Debit));
            t2.Start();

            Console.ReadKey();
        }

        static void Credit()
        {
            for (int i = 0; i < 15; i++)
            {
                lock (obj)
                {
                    balance += 100;
                    Console.WriteLine("After crediting,balance is {0}", balance);
                }
            }
        }
        static void Debit()
        {
            for (int i = 0; i < 15; i++)
            {
                lock (obj)
                {
                    balance -= 100;
                    Console.WriteLine("After debiting,balance is {0}", balance);
                }
            }
        }
    }
}

當然以上是最基本方法,可以用delegate、lambda表達式等簡寫,具體請參考下篇博文。

小結:多線程調用函數就是這樣。在Winform中,控件綁定到特定的線程,從另一個線程更新控件,不應該直接調用該控件的成員,這個非常有用,下篇博文講。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM