部落格觀察

聯絡我

Software

最新回應

System.Threading 命名空間提供了執行緒的建立,讓開發者省去了不少程式碼。

使用多執行緒時先匯入System.Threading

如何建立執行緒

1.建立一個方法

private void RunSample01()
{
    Console.WriteLine("執行緒:{0}",Thread.CurrentThread.ManagedThreadId);
}

 

 

2.建立ThreadStart委派,它是用來表示在執行緒上執行的方法。

ThreadStart myRun = new ThreadStart(RunSample01);

 

 

3.建立Thread 類別,它是用來建立和控制執行緒,設定執行緒的優先權,並取得它的狀態。

Thread myThread = new Thread(myRun);

4.啟動執行緒

myThread.Start();

 

 

如何建立多重執行緒

        private void button2_Click(object sender, EventArgs e)
        {
            //1.建立ThreadStart委派
            ThreadStart myRun = new ThreadStart(RunSample01);
            for (int i = 0; i < 6; i++)
            {
                try
                {
                    //2.建立Thread 類別
                    Thread myThread = new Thread(myRun);
                    //3.啟動執行緒
                    myThread.Start();
                }
                catch (Exception)
                {
                    //例外發生則終止迴圈執行
                    break;
                }
            }
 
        }

如何傳遞參數給多執行緒

ThreadStart委派沒有傳遞參數的功能,在實際應用上我們常需要傳遞參數,這時就要改用ParameterizedThreadStart 委派ParameterizedThreadStart 委派用法與ThreadStart委派大同小異,只是多了參數傳遞機制。

private void button3_Click(object sender, EventArgs e)
        {
            //1.建立ParameterizedThreadStart委派
            ParameterizedThreadStart myPar = new ParameterizedThreadStart(RunSample02);
            //2.建立Thread 類別
            Thread myThread01 = new Thread(myPar);
            Thread myThread02 = new Thread(myPar);
            //3.啟動執行緒並帶入參數
            myThread01.Start("我是多執行緒第一號");
            myThread02.Start("我是多執行緒第二號");
        }        
private void RunSample02(object o)
        {
            string myStr = o as string;
            //string myStr = (string)o;
            if (myStr == null)
            {
                myStr = (string)o;
            }
            else
            {
                for (int i = 0; i < 6; i++)
                {
                    Console.WriteLine("{0}:{1}", myStr, Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(1000);
                }
            }
        }

 

如何跨執行緒存取UI

當我試著用WinFrom寫多執行緒時,卻出現了以下錯誤訊息

跨執行緒作業無效: 存取控制項 'textBox1' 時所使用的執行緒與建立控制項的執行緒不同。

詢問高手後有三種方法解決:

1.Form.CheckForIllegalCrossThreadCalls = False

2.建立委派

3.使用BackgroundWorker

第一種方法,據說不安全,但我也不曉得哪裡不安全,但用起來還蠻方便的。

第二種方法,比較正統使用委派的方式,若爾後需要改任何控制項的文字時(需有text屬性的),呼叫 myU即可。

        private delegate void myUICallBack(string myStr, Control ctl);
        private void myUI(string myStr, Control ctl)
        {
            if (this.InvokeRequired)
            {
                myUICallBack myUpdate = new myUICallBack(myUI);
                this.Invoke(myUpdate, myStr, ctl);
            }
            else
            {
                ctl.Text = myStr;
            }
        }

 

 

 

第三種方法,使用BackgroundWorker,更強大的功能讓我們省去了上述繁雜的動作。

 

更詳細的UI跨執行緒請參考:Windows Form UI優化入門課 – 非同步作業

C#範例下載:C#.NET多執行緒.rar

 

新手發帖請多包涵


回應

  • 五秒 2009/2/18 下午 04:28 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    第一種方法不安全,是因為類似行程同步存取會出現的問題!~需要自己做行程同步的控管!

  • yc421206 2009/2/23 下午 09:58 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    to 五秒 :

    原來會有同步資料的不安全,謝謝你~

  • SoulOut 2009/11/16 下午 11:13 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    請問如果要在Form1以外的類別存取Form1的UI元件該如何做呢?

  • yc421206 2009/11/17 上午 11:07 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    to SoulOut :

    在其他類別引用Form1

  • SoulOut 2009/11/17 下午 04:50 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    再請問一點就是我有試過可是不知道是不是我引用的方式不對

    Class Mytest
    {
    public void test()
    {
    Form1 fm1 = new Form1();
    fm1.textBox1.Text =
    "This is a test";
    }
    }

    然後我在Form1.cs下呼叫
    public partial class Form1 : Form
    {
    private void button1_Click(object sender, EventArgs e)
    {
    Mytest tryIt = new Mytest();
    Mytest.test();
    }

    可是Form1的textBox沒有印出什麼東西?
    我有另外再試在test方法內加入fm1.Show();
    這樣textBox會印出東西來,但是就變成畫面上
    有兩個Form1

  • yc421206 2009/11/18 上午 10:57 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    to SoulOut :

    我不知您的用意如何?

    但你在Form1再次new Form1,理所當然會出現兩個Form1

  • yc421206 2009/11/19 上午 11:00 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    to SoulOut :

    你如果只是單純要引用Form1的東西,不要用new,它的生命週期已經還沒結束,因為它還活著~直接用就好了
    public void test()
    {
    Form1 fm1;
    fm1.textBox1.Text =
    "This is a test";
    }

    當然~你Form1上的控制項要給權限讓其它類別用,不能用private。

  • SoulOut 2009/11/19 下午 07:45 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    謝謝版主的解答,對於物件、類別跟方法的應用我現階段還在摸索;的確只是單純要想在其它類別引用Form1上的UI;如果不使用new來產生一個新的個體,fm1欄位會是null,即產生exception

  • yc421206 2009/11/20 上午 12:04 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    to SoulOut :

    不好意思~我早上測是可以的~但好像貼錯了>"<

    in class

    public  class Mytest
    {
       public void Test(Form1 fm1)
        {
            fm1.textBox1.Text = "text";
        }
    }

    in button

    private void button1_Click(object sender, EventArgs e)
    {
        Mytest tryIt = new Mytest();
        tryIt.Test(this);
    }

    把還活著的Form1丟出去。請原諒我的腦殘

     

     

     

  • SoulOut 2009/11/20 上午 12:17 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    快別這麼說,您的Blog上的技巧對很多人而言是很有幫助的;又學到一招^^謝謝!

  • billchung 2009/11/20 上午 12:31 回覆

    # re: [C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI

    Control.CheckForIllegalCrossThreadCalls=False 真的不要用. MSDN上有這段備註 : CheckForIllegalCrossThreadCalls 設定為 true,可以在偵錯時更容易找到並診斷這種執行緒活動。請注意,如果在偵錯工具之外啟動應用程式,不當的跨執行緒呼叫總是會引發例外狀況。

    http://msdn.microsoft.com/zh-tw/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx

     


*標 題:

*姓 名:

 電子郵件: (將不會被顯示)

 個人網頁:

*回應

登入後使用進階評論

Please add 4 and 1 and type the answer here: