The problem is you aren't just being held back by the maximum number of concurrent operations. HttpWebRequests
are throttled by nature (I believe the default policy allows only 2 at any given time), so you have to override that behaviour too. Please refer to the code below.
Imports System.Diagnostics
Imports System.IO
Imports System.Net
Imports System.Threading
Imports System.Threading.Tasks
Public Class Form1
''' <summary>
''' Test entry point.
''' </summary>
Private Sub Form1_Load() Handles MyBase.Load
' Generate enough words for us to test thoroughput.
Dim words = Enumerable.Range(1, 100) _
.Select(Function(i) "Word" + i.ToString()) _
.ToArray()
' Maximum theoretical number of concurrent requests.
Dim maxDegreeOfParallelism = 24
Dim sw = Stopwatch.StartNew()
' Capture information regarding current SynchronizationContext
' so that we can perform thread marshalling later on.
Dim uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()
Dim uiFactory = New TaskFactory(uiScheduler)
Dim transformTask = Task.Factory.StartNew(
Sub()
' Apply the transformation in parallel.
' Parallel.ForEach implements clever load
' balancing, so, since each request won't
' be doing much CPU work, it will spawn
' many parallel streams - likely more than
' the number of CPUs available.
Parallel.ForEach(words, New ParallelOptions With {.MaxDegreeOfParallelism = maxDegreeOfParallelism},
Sub(word)
' We are running on a thread pool thread now.
' Be careful not to access any UI until we hit
' uiFactory.StartNew(...)
' Perform transformation.
Dim url = "http://api.mymemory.translated.net/get?q=" & word & "!&langpair=de|it&de=somemail@christmas.com"
Dim request = DirectCast(WebRequest.Create(url), HttpWebRequest)
' Note that unless you specify this explicitly,
' the framework will use the default and you
' will be limited to 2 parallel requests
' regardless of how many threads you spawn.
request.ServicePoint.ConnectionLimit = maxDegreeOfParallelism
Using response = DirectCast(request.GetResponse(), HttpWebResponse)
Using myreader As New StreamReader(response.GetResponseStream())
Dim rawresp = myreader.ReadToEnd()
Debug.WriteLine("Raw:" & rawresp)
' Transform the raw response here.
Dim processed = rawresp
uiFactory.StartNew(
Sub()
' This is running on the UI thread,
' so we can access the controls,
' i.e. add the processed result
' to the data grid.
Me.Text = processed
End Sub, TaskCreationOptions.PreferFairness)
End Using
End Using
End Sub)
End Sub)
transformTask.ContinueWith(
Sub(t As Task)
' Always stop the stopwatch.
sw.Stop()
' Again, we are back on the UI thread, so we
' could access UI controls if we needed to.
If t.Status = TaskStatus.Faulted Then
Debug.Print("The transformation errored: {0}", t.Exception)
Else
Debug.Print("Operation completed in {0} s.", sw.ElapsedMilliseconds / 1000)
End If
End Sub,
uiScheduler)
End Sub
End Class