2017-10-08 24 views
-2

我有一個多行文本框,我想用多線程處理每一行。如何防止使用相同變量的線程

該文本框可能有很多行(1000+),但不是多個線程。我想使用自定義數量的線程來讀取所有這些超過1000行,沒有任何重複(如在每個線程讀取UNIQUE行,如果一行已被其他線程讀取,而不是再次讀取)。

我有什麼權利現在:

private void button5_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < threadCount; i++) 
    { 
     new Thread(new ThreadStart(threadJob)).Start(); 
    } 
} 

private void threadJob() 
{ 
    for (int i = 0; i < txtSearchTerms.Lines.Length; i++) 
    { 
     lock (threadLock) 
     { 
      Console.WriteLine(txtSearchTerms.Lines[i]); 
     } 
    } 
} 

它啓動線程的正確數量,但他們都讀同一變量多次。

+0

按線程數除文本框,並使每個線程只讀自己的池 – Marqin

+0

做任何這些答案爲你工作@gafs? – mjwills

回答

3

單獨的數據收集和數據處理以及計算後的下一個可能步驟。通過使用ConcurrentBag<T>,您可以安全地收集並行計算的結果,這只是線程安全的集合。
然後你不需要擔心「鎖定」對象,所有的行將被「處理」一次。
1.收集數據
2.並聯
3.拉手計算結果

private string Process(string line) 
{ 
    // Your logic for given line 
} 

private void Button_Click(object sender, EventArgs e) 
{ 
    var results = new ConcurrentBag<string>(); 

    Parallel.ForEach(txtSearchTerms.Lines, 
        line => 
        { 
         var result = Process(line); 
         results.Add(result); 
        }); 

    foreach (var result in results) 
    { 
     Console.WriteLine(result); 
    } 
} 

執行收集的數據在默認情況下Parallel.ForEach作爲底層調度程序提供將使用盡可能多的線程。

您可以通過將ParallelOptions的實例傳遞給Parallel.ForEach方法來控制已用線程的數量。

var options = new ParallelOptions 
{ 
    MaxDegreeOfParallelism = Environment.ProcessorCount 
}; 
var results = new ConcurrentBag<string>(); 
Parallel.ForEach(values, 
       options, 
       value => 
       { 
        var result = Process(value); 
        results.Add(result); 
       }); 
-1

有很多方法可以做到你想要的。

採取額外的類字段:

private int _counter; 

用它來代替循環指數。增加它在鎖內:

private void threadJob() 
{ 
    while (true) 
    { 
     lock (threadLock) 
     { 
      if (_counter >= txtSearchTerms.Lines.Length) 
       return; 
      Console.WriteLine(txtSearchTerms.Lines[_counter]); 
      _counter++; 
     } 
    } 
} 

它的工作原理,但它效率非常低。

讓我們考慮另一種方式。每個線程將獨立於其他線程處理其數據集的一部分。

public void button5_Click(object sender, EventArgs e) 
{ 
    for (int i = 0; i < threadCount; i++) 
    { 
     new Thread(new ParameterizedThreadStart(threadJob)).Start(i); 
    } 
} 

private void threadJob(object o) 
{ 
    int threadNumber = (int)o; 
    int count = txtSearchTerms.Lines.Length/threadCount; 
    int start = threadNumber * count; 
    int end = threadNumber != threadCount - 1 ? start + count : txtSearchTerms.Lines.Length; 

    for (int i = start; i < end; i++) 
    { 
     Console.WriteLine(txtSearchTerms.Lines[i]); 
    } 
} 

這是更有效,因爲線程不上了鎖等待。但是,數組元素不是以一般方式處理的。

0

考慮使用Parallel.ForEach遍歷Lines數組。 它就像正常的foreach循環(即每個值只會被處理一次),但工作是並行完成的 - 具有多個線程(Task)。如果你想不只是執行東西

using System.Threading.Tasks; 

另外,也回報:

var data = txtSearchTerms.Lines; 
var threadCount = 4; // or whatever you want 

Parallel.ForEach(data, 
    new ParallelOptions() { MaxDegreeOfParallelism = threadCount }, 
    (val) => 
    { 
     //Your code here 
     Console.WriteLine(val); 
    }); 

上面的代碼將需要這條線在你的文件的頂部添加/ project然後改爲:

var results = data.AsParallel(new ParallelLinqOptions() 
{ 
    MaxDegreeOfParallelism = threadCount 
}).Select(val => 
{ 
    // Your code here, I just return the value but you could return whatever you want 
    return val; 
}).ToList(); 

它仍然並行執行代碼,但也返回一個List(在這種情況下,原始的TextBox中的值相同)。最重要的是,List將與您的輸入順序相同。

相關問題