[英]Using C# ConcurrentBag<T> with multiple producers and a single consumer
[英]Using Threads and ConcurrentBag in C#
我正在用C#構建一個簡單的端口掃描程序。 我已經具有端口掃描功能,並且用戶可以傳遞要使用的線程數和IP地址范圍。 因此,目前,我已經解析了范圍並創建了一個ConcurrentBag
,其中包含該范圍內的所有IP地址。 我也有一個線程數組。 因此,部分看起來像這樣:
var ipsInRange = IPAddressRange.Parse(range);
Thread[] hostThreads = new Thread[(int)threads];
ConcurrentBag<IPAddress> ips = new ConcurrentBag<IPAddress>();
foreach (var ip in ipsInRange)
{
ips.Add(ip);
}
IPAddress address;
while (!ips.IsEmpty)
{
if (ips.TryTake(out address))
{
PortScanner ps = new PortScanner(address);
ps.Scan();
}
}
// I want to assign each thread one IP address, create a new PortScanner
// instance as above, and scan the IP. I want to delete the scanned IPs
// from the bag. When the thread finishes with scanning, I want to assign
// a new one to it. I want to continue like this until the bag is empty,
// i.e. all the IPs are processed.
// So, simply I want to scan multiple IPs at the same time, using the above
// thread array and the ConcurrentBag containing list of IPs.
雖然,我以前沒有使用過Threads
和ConcurrentBag
,但是我想要實現的內容寫在上面的注釋中。 知道如何將上述線程合並到應用程序中嗎?
如我所見的解決方案:
創建幾個任務,從冷卻中獲取IP並對其進行掃描。
var bc = new BlockingCollection<string>(); //... bc.Add(ip); //add addresses from another thread, or smth else //... for(int i = 0; i < 10; i++) { Task.Run(()=> { var address = bc.Take(); PortScanner ps = new PortScanner(address); ps.Scan(); }); }
您有10個線程,這些線程掃描地址,它們將等待,而收集可以為它們提供下一個元素。
我建議使用任務並行庫,而不要自己管理線程。 它導致代碼簡短易讀,並且您不需要處理線程或ConcurrentBag。
如果在端口掃描開始之前就知道了所有IP地址(即,您不需要在端口掃描期間添加/刪除IP地址),則代碼可以像下面這樣簡單:
var ipsInRange = IPAddressRange.Parse(range);
var options = new ParallelOptions()
{
MaxDegreeOfParallelism = 5// Set number of IP addresses to be processed concurrently
};
Parallel.ForEach(
ipsInRange,
options,
(address) => { PortScanner ps = new PortScanner(address); ps.Scan(); });
如果需要支持在進行端口掃描時可以修改IP地址列表(來自其他線程)的方案,則需要將ipsInRange
集合包裝在BlockingCollection中 ,但是從您的問題看來,我不需要它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.