有人可以展示如何在不創建多個線程的情況下發出併發請求嗎?例如,我想要一個能夠發出100個Web請求的程序,並且我不想在任何時候發出超過8個併發請求。我不想爲8個併發請求創建8個線程。當線程發出異步請求時,可以使用同一個線程發出下一個請求,依此類推。我很抱歉,但我無法把頭圍繞在這,並希望看到最好的解決方案。如果不清楚,我所說的請求是異步的。我希望看到一個不使用任何鎖的解決方案,並使用內置的類來完成這項工作。如何在不創建多個線程的情況下發出併發請求?
這是我想出的一些代碼,但它沒有做它應該做的事情。
Task.Run(async() =>
{
var outstandingRequests = 0;
var requestCount = 0;
var tasks = new List<Task>(concurrentRequests);
while (requestCount < maxRequests)
{
if (outstandingRequests < concurrentRequests)
{
tasks.Add(svc.GetDataAsync()); // a method that makes an async request
Interlocked.Increment(ref outstandingRequests);
}
else
{
var t = await Task.WhenAny(tasks);
Interlocked.Decrement(ref outstandingRequests);
Interlocked.Increment(ref requestCount);
}
}
await Task.WhenAll(tasks);
}).Wait();
輸出:
[] 1 Sending Request...Received Response 490,835.00 bytes in 15.6 sec
[] 2 Sending Request...
[] 3 Sending Request...
[] 4 Sending Request...
[] 5 Sending Request...
[] 6 Sending Request...
[] 7 Sending Request...
[] 8 Sending Request...
[] 9 Sending Request...
我已經設置concurrentRequests
至5,所以有一些bug上述代碼作爲它正在並行8名的請求。最初它只能並行處理5個請求,但只要一個請求完成,它就會發出4個請求(應該只發送一個請求)。
不得不修復了一些bug,但是這一切現在工作了:
Task.Run(async() =>
{
var outstandingRequests = 0;
var requestCount = 0;
// adding and removing from a List<> at the same time is not thread-safe,
// so have to use a SynchronizedCollection<>
var tasks = new SynchronizedCollection<Task>();
while (requestCount < maxRequests)
{
if (outstandingRequests < concurrentRequests)
{
tasks.Add(svc.GetDataAsync(uri)); // this will be your method that makes async web call and returns a Task to signal completion of async call
Interlocked.Increment(ref outstandingRequests);
Interlocked.Increment(ref requestCount);
}
else
{
**tasks.Remove(await Task.WhenAny(tasks));**
Interlocked.Decrement(ref outstandingRequests);
}
}
await Task.WhenAll(tasks);
}).Wait();
如果有更好的方式來做到這一點,請讓我知道。
「沒有創建多個線程」和「當線程發出異步請求時,同一個線程可以用於發出下一個請求」是衝突的語句。 – 2013-03-17 03:03:37