2012-02-28 29 views
2

我有一些C#線程必須根據數字做一些工作,但是我不確定如何讓線程對象返回主程序類。我需要它告訴主對象它已經找到了結果和結果,然後它可以停止線程。C#獲取線程類來與主類進行通信

 Worker Worker1 = new Worker(input, 1073741824, 2147483647); 
     Worker Worker2 = new Worker(input, 0, 1073741824); 
     Thread ThreadRace1 = new Thread(new ThreadStart(Worker1.Start)); 
     Thread ThreadRace2 = new Thread(new ThreadStart(Worker2.Start)); 
     ThreadRace1.Start(); 
     ThreadRace2.Start(); 
+0

您使用的是什麼版本的.NET? – 2012-02-28 21:20:15

+0

哪個版本的.Net?如果V4 +,您可以使用非常容易使用的Task類。 – 2012-02-28 21:20:29

+0

完成工作後返回工作人員並加入主題。 – CodeCaster 2012-02-28 21:20:32

回答

1

已經有名爲BackgroundWorker一個框架類,旨在幫助您在最小化的代碼,你需要編寫執行後臺處理量。您可以讓主線程註冊到BackgroundWorker上的各種回調事件,特別是BackgroundWorker線程完成其任務時的「OnRunWorkerCompleted」事件。

下面是如何設置它的一個簡單示例。您將在主線程中啓動BackgroundWorker實例。

void SetupBackgroundworkers() 
    { 
     BackgroundWorker backgroundWorker1 = new BackgroundWorker(); 
     backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); 
     backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); 

     BackgroundWorker backgroundWorker2 = new BackgroundWorker(); 
     backgroundWorker2.DoWork += new DoWorkEventHandler(backgroundWorker2_DoWork); 
     backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker2_RunWorkerCompleted); 

     // Start the workers 
     backgroundWorker1.RunWorkerAsync(); 
     backgroundWorker2.RunWorkerAsync(); 
    } 

    void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     var result = e.Result; // read result 
    } 

    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     var result = e.Result; // read result 
    } 

    void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // perform work... 
     e.Result = 1; // your result 
    } 

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // perform work... 
     e.Result = 2; // your result 
    } 
0

一些可能性:

  1. 通過主類的每個工人經由工人構造參考。這樣,您就可以調用public方法由主類公開
  2. 呼叫public static方法,通過主類(最髒的解決方案,避免不惜一切代價)暴露
  3. 如果您正在使用C#4.0中,你可以使用任務並行庫的WaitAny方法來獲取控制在主類當工人的任何完成

前兩個選項需要明確的併發控制措施(確保後一個工人示意主類,沒有其他工人可以)。

2

如果您使用的是.NET 4.0+,那麼您可以使用TPL。該守則將是這個樣子:

var task1 = Task.Factory.StartNew<int>(()=> 
    { 
     //Do Work...use closures, or you can pass boxed arguments in 
     //via StartNew params 
     return 1;//return the value that was computed 
    }); 
var task2 = Task.Factory.StartNew<int>(()=> 
    { 
     //Do Work 
     return 2;//return the value that was computed 
    }); 
task1.ContinueWith((previousTask)=> 
    { 
     //Return back to the main thread 
     label1.Text += "The value of task1 is going to be 1-->" 
         + previousTask.Result; 
    } 
    , new CancellationTokenSource().Token, TaskContinuationOptions.None, 
    //This is to auto invoke back into the original thread 
    TaskScheduler.FromCurrentSynchronizationContext()); 
task2.ContinueWith((previousTask)=> 
    { 
     //Return back to the main thread 
     label1.Text += "The value of task2 is going to be 2-->" 
         + previousTask.Result; 
    } 
    , new CancellationTokenSource().Token, TaskContinuationOptions.None, 
    //This is to auto invoke back into the original thread 
    TaskScheduler.FromCurrentSynchronizationContext()); 

如果你不需要處理每一個,因爲他們進來,那麼你可以等到他們全部返回:

var taskList = new List<Task>{task1,task2}; 
Task.Factory.ContinueWhenAll(taskList.ToArray(), 
    (tasks)=> 
    { 
     label1.Text = "Results are: "; 
     foreach(var task in tasks) 
     { 
      //process each task 
      label1.Text += task.Result + "|"; 
     } 
    }, 
    new CancellationTokenSource().Token, TaskContinuationOptions.None, 
    //This is to auto invoke back into the original thread 
    TaskScheduler.FromCurrentSynchronizationContext()); 
+0

我只是想知道,如何才能讓對象在找到答案後立即傳回數據? – 2012-02-28 21:31:30

+0

假設你正在返回一個int,更新了我的迴應 – 2012-02-28 21:37:46

0

您可以:

設置一個全局變量,從內螺紋(但當時如果將多個線程使用相同的增值經銷商,你將有同步問題)

OR

使用ParameterisedThreadStart允許傳遞一個對象(您可以使用out(引用)變量。

,或者可以創建具有方法上的任何線程完成被稱爲它啓動threadmanager類 - 的方法可能是簽字的(但是這是給你和我是半僞代碼)

static class ThreadManager{ 

    ctor Main(blah blah){//do thread creation and in loop you can call Threadmanager.ThreadFinished as it is static method} 

    public static object ThreadFinished(Thread theThreadThatJustFInished, object data) 
    { 
     //do update on ThreadManager based on object data and Thread type 
    } 

}