2010-08-06 18 views
0

我有一個小問題,與此代碼:參數過路線程C#ERROR

這是應用程序的「主」的方法:

private Thread main_process; 
private Clases.GestorTR processor; 

public void begin() 
{ 
    processor = new Clases.GestorTR(); 
    main_process = new Thread(new ThreadStart(processor.ExecuteP)); 
    main_process.Start(); 
} 

我創建了一個線程來處理其他「Transacction Threads」避免阻塞GUI。 這是方法ExecuteP,處理器對象上:

public void ExecuteP() 
{ 
// Readed an DataTable with BD transacction, filled with numbers 
foreach (DataRow dr in dtResults.Rows) 
{ 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    ThreadStart starter; 
    starter = delegate { new QueryBD.QueryCounter(Local_number); }; 
    new Thread(starter).Start(); 
} 
} 

這是QueryBD類的QueryCounter方法:

.... 
private void QueryCounter(int _counter) 
    { 
     logs.log("ON QUERY_PROCESS: " + _counter); 
    } 
... 

現在,問題。在調用委託時,一些線程正在穿越參數。例如,在foreach方法中,日誌顯示正確(1,2,3,4,5,6,7,8),但在QueryCounter方法中(每次調用新線程時,日誌顯示爲1,1 ,1,4,5,6,6,8)例如,我也試過使用鎖,但問題是一樣的,同樣使用ThreadPool方法測試,結果相同 我想我錯過了東西在foreach循環,因爲如果我調試首次運行時,線程啓動,但沒有在日誌中動作

感謝!

回答

0

你應該嘗試改變你的代碼是一樣的某些部分:

public void ExecuteP() 
{ 
    QueryBD facade = new QueryBD. 
    foreach (DataRow dr in dtResults.Rows) 
    { 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    new Thread(new ParameterizedThreadStart(facade.QueryCounter)).Start(Local_number); 
    } 
} 

public void QueryCounter(object _counter) 
{ 
    ... 
} 

希望它有效。

Btw。我創建了一個名爲Facade的對象,並將該對象傳遞給各個線程。它也可以導致一些副作用,是否會有線程在外觀對象代碼敏感的部分,所以你也可以考慮鎖定有:

public void QueryCounter(object _counter) 
{ 
    lock(this) 
    { 
     // 
    } 
} 

或給每個線程提供新QueryBD,但它可能會影響性能。

編輯:喂,4兩件事:

  1. 在使用ParametrizedThread,通過了可變啓動線程(thread.Start(variable))在呼叫的時間被複制的方法。這個複製的變量然後在子線程中使用。匿名代理工作不同。它保持對變量的引用,所以當變量被子線程使用時,它可以通過父線程中的時間進行更改。這就是爲什麼你有不可預知的行爲。

  2. 更好的解釋你可以在這裏找到:Differing behavior when starting a thread: ParameterizedThreadStart vs. Anonymous Delegate. Why does it matter?

  3. 性能取決於。如果你的對象的創建過程很繁瑣(例如,它會在每次創建時創建與數據庫的新連接),那麼創建很多這樣的對象會嚴重影響性能 - 這就是鎖定更好的地方。如果創建對象很輕,則可以根據需要創建任意數量的對象。這取決於。

  4. 如果您希望您的代碼按照定義的順序運行,則根本不應該使用線程。如果要保留執行順序,順序調用是正確的方法 - 請參閱Hans Passant解釋。

+0

嗨!我沒有使用ParameterizedThreadStart來獲得一個「更乾淨」的代碼,並避免像字符串數組那樣解析對象來獲取所有參數,但是我錯了。現在,我正在研究爲什麼ThreadPool和委託匿名方法不起作用,有什麼想法? 關於鎖,性能如何:USING LOCK with 1 base object VS.爲每個線程提供一個新實例?思考速度,每次提供新實例並不是更快的方法? 非常感謝, – Jabab 2010-08-06 21:57:50

+0

使用WS調用和BD訪問的完整流程。速度和多個請求是一個 「必須」: 隨着每次調用新的對象: START 16:00:08.8915628 FINISH 16:00:12.0278610 總時間:3.1362982 隨着鎖定和單鹼基對象: START 16 :02:33.3375315 完成16:02:38.9863682 總時間:5.6488367 – Jabab 2010-08-06 22:12:49

+0

嘿,檢查編輯部分在我的答案。該評論部分是對此的簡要介紹。保重。 – jwaliszko 2010-08-06 23:00:54