首頁 > 後端開發 > C#.Net教程 > C# 多執行緒參數傳遞

C# 多執行緒參數傳遞

黄舟
發布: 2017-02-17 10:51:30
原創
1737 人瀏覽過

1、透過實體類別來傳遞(可以傳遞多個參數與取得回傳值),demo如下:

需要在執行緒中呼叫的函數:

namespace ThreadParameterDemo
{
    public class FunctionClass
    {
        public static string TestFunction(string name, int age)
        {
            //内部处理省略
            return name + " 的年龄是:" + age;
        }
    }
}
登入後複製

namespace ThreadParameterDemo
{
    /// <summary>
    /// 过渡类
    /// </summary>
    public class TransitionalClass
    {
        private string name = string.Empty;
        private int age;
        public string acceptResults = string.Empty;
        public TransitionalClass(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        public void TestFunction()
        {
            acceptResults = FunctionClass.TestFunction(this.name, this.age);
        }
    }
}
登入後複製

呼叫:


  private void Form1_Load(object sender, EventArgs e)
        {
            //实例化ThreadWithState类,为线程提供参数  
            TransitionalClass tc = new TransitionalClass(" Jack", 42);
            // 创建执行任务的线程,并执行  
            Thread t = new Thread(new ThreadStart(tc.TestFunction));
            t.Start();
            //获取返回值,通过 tc.acceptResults;  
        }
登入後複製


ground的問題,如果IsBackground為false的,則Windows程式在退出的時候,不會為你自動退出該線程。也就是實際上你的應用程式未結束。

MSDN建議:多線程方法調用提供參數的最佳方法是將目標方法包裹在類別中,並為該類別定義字段,這些字段將被用作新線程的參數。 

       這種方法的優點是,任何時候想要啟動新線程,都可以創建類別的新實例,該實例帶有自身的參數。

        BackgroundWorker 類別

🜎值中的函數是沒有回傳值的參數的參數

2 能完美解決參數和回傳值的是使用非同步呼叫的方式。非同步呼叫和Thread相比,一個最大的劣勢是不能控制其優先權。

具體程式碼如下:

        public delegate string delegateFunction(string name,int age);//委托
        delegateFunction df;
        private void Form1_Load(object sender, EventArgs e)
        {
            //指向需要调用的方法
            df = new delegateFunction(FunctionClass.TestFunction);
            string name = "my name";//输入参数 
            int age = 19;
            IAsyncResult result = df.BeginInvoke(name,age, null, null);
            string myResult = df.EndInvoke(result);//用于接收返回值 
            MessageBox.Show(myResult);
        }
登入後複製

化簡:

透過這種方式產生新執行緒是運行在後台的(background),優先權為normal

3、使用BackgroundWorker

多執行緒值完成最簡單方法是使用執行緒來完成執行任務,然後完成執行緒嗎用事件處理程序處理結果。

小注:

BackgroundWorker 元件用來執行諸如資料庫事務、檔案下載等耗時的非同步操作。 在應用程式中新增一個BackgroundWorker實例,如果使用的是VS,可以從工具上直接拖曳到應用程式:


 public Func<string, int, string>  df;//委托
        private void Form1_Load(object sender, EventArgs e)
        {
            //指向需要调用的方法
            df += FunctionClass.TestFunction;
            string name = "my name";//输入参数 
            int age = 19;
            IAsyncResult result = df.BeginInvoke(name, age, null, null);
            string myResult = df.EndInvoke(result);//用于接收返回值 
            MessageBox.Show(myResult);
        }
登入後複製

      

BackgroundWorker backgroundWorker1 = new BackgroundWorker();
登入後複製
 當呼叫此方時,BackgroundWorker 透過觸發DoWork 事件,開始執行後台操作,DoWork 事件的程式碼是在另一個執行緒執行的。

       當後台作業完成以後,無論是completed 或cancelled,則RunWorkerCompleted 事件被觸發,透過此方法可以將後台作業的完成結果回饋給使用者。

       另外,透過RunWorkerCompletedEventArgs實例的Cancelled 屬性,以判斷是否為Cancel操作使得後台作業終止。

具體demo如下:


using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            //TransitionalClass tc = new TransitionalClass("xiaoming", 10);
            //ThreadPool.QueueUserWorkItem(new WaitCallback(TransitionalClass.TestFunction), tc);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.TestArea2();
        }

        private System.ComponentModel.BackgroundWorker BackgroundWorker1
    = new System.ComponentModel.BackgroundWorker();

        private void TestArea2()
        {
            InitializeBackgroundWorker();

            AreaClass2 AreaObject2 = new AreaClass2();
            AreaObject2.Base = 30;
            AreaObject2.Height = 40;

            // Start the asynchronous operation.
            BackgroundWorker1.RunWorkerAsync(AreaObject2);
        }

        private void InitializeBackgroundWorker()
        {
            // Attach event handlers to the BackgroundWorker object.
            BackgroundWorker1.DoWork +=
                new System.ComponentModel.DoWorkEventHandler(BackgroundWorker1_DoWork);
            BackgroundWorker1.RunWorkerCompleted +=
                new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted);
        }

        private void BackgroundWorker1_DoWork(
            object sender,
            System.ComponentModel.DoWorkEventArgs e)
        {
          //在执行DoWork 事件时,DoWorkEventArgs 实例的Result 属性,返回值到用户;在RunWorkerCompleted 事件里,RunWorkerCompletedEventArgs 实例的Result 属性接收值;
            AreaClass2 AreaObject2 = (AreaClass2)e.Argument;
            // Return the value through the Result property.
            e.Result = AreaObject2.CalcArea();
        }

        private void BackgroundWorker1_RunWorkerCompleted(
            object sender,
            System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            // Access the result through the Result property. 
            double Area = (double)e.Result;
            MessageBox.Show("The area is: " + Area.ToString());
        }
    }
}
登入後複製

demo代碼來自MSDN:

4、如果不如返回值的時候,該怎麼優雅的寫呢?匿名函數啊



FunctionClass類新增,測試函數如下:

   public static void TestFunction2(string name, int age)
        {
            //内部处理省略            
        }
登入後複製



如果透過WCF來呼叫的話,應該把起執行緒的函數放到服務端,如果放到客戶端,很容易因為WCF客戶端的時間限制,造成主程式的莫名崩潰。

崩潰的原因主要是客戶端wcf回應時間是有限制。

 以上就是C# 多執行緒參數傳遞的內容,更多相關內容請關注PHP中文網(www.php.cn)!


來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板