一、經過實體類來傳遞(可以傳遞多個參數與獲取返回值),demo例如如下:html
需要在線程中調用的函數:數據庫
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; }
小注:多線程
必須注意IsBackground的問題。假設IsBackground爲false的,則Windows程序在退出的時候,不會爲你本身主動退出該線程。也就是實際上你的應用程序未結束。異步
MSDN推薦:多線程方法調用提供參數的最好辦法是將目標方法包裹在類中,併爲該類定義字段,這些字段將被用做新線程的參數。async
這樣的方法的長處是,不論何時想要啓動新線程。都可以建立類的新實例,該實例帶有自身的參數。函數
ThreadStart中的函數是沒有返回值和參數的post
二、異步調用中的參數和返回值
詳細代碼例如如下:this
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); }簡化:
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); }
小注:spa
經過這樣的方式生成新線程是運行在後臺的(background),優先級爲normal
三、使用 BackgroundWorker
多線程返回值最簡單方法是:使用 BackgroundWorker 組件來管理線程,在任務完畢時引起事件,而後用事件處理程序處理結果。
小注:
BackgroundWorker 組件用來運行諸如數據庫事務、文件下載等耗時的異步操做。
在應用程序中加入一個BackgroundWorker實例,假設用的是VS,可以從工具上直接拖到應用程序:
BackgroundWorker backgroundWorker1 = new BackgroundWorker();爲了開始在後臺操做,必須調用BackgroundWorker的RunWorkerAsync()方法。當調用此方時,BackgroundWorker 經過觸發DoWork 事件,開始運行後臺操做。DoWork 事件的代碼是在還有一個線程裏運行的。
詳細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()); } } }
參考文章:點擊打開連接
四、假設不如返回值的時候。應該怎麼優雅的寫呢?匿名函數啊
public static void TestFunction2(string name, int age) { //內部處理省略 }調用例如如下:
private void Form1_Load(object sender, EventArgs e) { Thread t1 = new Thread(new ThreadStart(delegate { FunctionClass.TestFunction2("eee", 5); })); t1.Start(); }
小注:
假設經過WCF來調用的話,應該把起線程的函數放到服務端,假設放到client。很是easy因爲WCFclient的時間限制,形成形成主程序的莫名崩潰。
崩潰的緣由主要是clientwcf響應時間是有限制。