非阻塞webrequests vb.net
我正在制作一个程序,必须尽快处理大约5000个字符串。其中大约2000个字符串必须通过webrequest转换到mymemory.translated.net。(请参阅下面的代码,JSON部分已删除,因为此处不需要) 代码本身工作正常,问题是它是一个阻塞代码,每个字符串大约需要1秒。我所有的琴弦都用了半个多小时。我需要将此代码转换为非阻塞代码,并同时进行多个调用。谁能告诉我怎么做?我想找一个背景工作人员,但那不会加快速度。。它只是在不同的线程上执行代码非阻塞webrequests vb.net,vb.net,multithreading,webrequest,Vb.net,Multithreading,Webrequest,我正在制作一个程序,必须尽快处理大约5000个字符串。其中大约2000个字符串必须通过webrequest转换到mymemory.translated.net。(请参阅下面的代码,JSON部分已删除,因为此处不需要) 代码本身工作正常,问题是它是一个阻塞代码,每个字符串大约需要1秒。我所有的琴弦都用了半个多小时。我需要将此代码转换为非阻塞代码,并同时进行多个调用。谁能告诉我怎么做?我想找一个背景工作人员,但那不会加快速度。。它只是在不同的线程上执行代码 谢谢 如果要发送10个并行请求,必须创建1
谢谢 如果要发送10个并行请求,必须创建10个BackgroundWorker。或者手动创建10个线程。然后进行迭代,每当工作线程/线程完成时,给它一个新任务 我不建议解雇5000个并行线程/工作线程,您必须小心: 这样的负载可能被解释为垃圾邮件或服务器的攻击。不要做得过火,也许可以和translated.net谈谈,问问他们接受的工作量。
还要考虑一下你的机器和你的互联网上游可以处理什么。问题在于你不仅仅是被最大数量的并发操作所阻碍
HttpWebRequests
本质上是受限制的(我认为默认策略在任何给定时间只允许2个),因此您也必须覆盖该行为。请参考下面的代码
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
导入系统诊断
导入System.IO
导入系统.Net
导入系统线程
导入System.Threading.Tasks
公开课表格1
'''
''测试入口点。
'''
私有子表单1_Load()处理MyBase.Load
“生成足够的单词,让我们测试完整性。
Dim words=可枚举范围(1100)_
.选择(函数(i)“Word”+i.ToString())_
.ToArray()
'并发请求的最大理论数量。
尺寸maxDegreeOfParallelism=24
Dim sw=秒表。开始新()
'捕获有关当前SynchronizationContext的信息
'以便我们以后可以执行线程编组。
Dim uiScheduler=TaskScheduler.FromCurrentSynchronizationContext()
Dim uiFactory=新任务工厂(uiScheduler)
Dim transformTask=Task.Factory.StartNew(
分()
'并行应用转换。
'Parallel.ForEach实现智能加载
“平衡,所以,因为每个请求都不会
'如果要做大量CPU工作,它将生成
“许多平行流——可能超过
'可用CPU的数量。
ForEach(words,带有{.MaxDegreeOfParallelism=MaxDegreeOfParallelism}的新ParallelOptions,
分(字)
'我们现在正在线程池线程上运行。
“在我们点击之前,请小心不要访问任何UI
'uiFactory.StartNew(…)
'执行转换。
Dim url=”http://api.mymemory.translated.net/get?q=“&word&”!&langpair=de | it&de=somemail@christmas.com"
Dim request=DirectCast(WebRequest.Create(url),HttpWebRequest)
'请注意,除非您明确指定,
'框架将使用默认值,而您
'将限制为2个并行请求
'无论生成多少线程。
request.ServicePoint.ConnectionLimit=maxDegreeOfParallelism
使用response=DirectCast(request.GetResponse(),HttpWebResponse)
将myreader用作新的StreamReader(response.GetResponseStream())
Dim rawrep=myreader.ReadToEnd()
Debug.WriteLine(“Raw:&rawrep”)
'在此处转换原始响应。
已处理尺寸=RAWREP
uiFactory.StartNew(
分()
'这是在UI线程上运行的,
“这样我们就可以访问控件,
'即添加处理后的结果
'到数据网格。
Me.Text=已处理
结束子任务,任务创建选项。首选公平性)
终端使用
终端使用
末端接头)
末端接头)
transformTask.ContinueWith(
Sub(t作为任务)
“总是把秒表停下来。
sw.Stop()
“我们又回到了UI线程上,所以我们
'如果需要,可以访问UI控件。
如果t.Status=TaskStatus.Faulted,则
Print(“转换错误:{0}”,t.Exception)
其他的
Debug.Print(“操作在{0}秒内完成”,sw.elapsedmillyses/1000)
如果结束
末端接头,
(调度程序)
端接头
末级
我会为每个请求创建一个任务,这样您就可以使用ContinueWith
对每个调用进行回调:
For Each InputString As String In myCollectionString
Tasks.Task(Of String).Factory.StartNew(Function(inputString)
Dim request As HttpWebRequest
Dim myreader As StreamReader
Dim response As HttpWebResponse
Dim rawResp As String = String.Empty
Try
Dim url As String = "http://api.mymemory.translated.net/get?q=" & inputString & "!&langpair=de|it&de=somemail@christmas.com"
request = DirectCast(WebRequest.Create(url), HttpWebRequest)
response = DirectCast(request.GetResponse(), HttpWebResponse)
myreader = New StreamReader(response.GetResponseStream())
rawResp = myreader.ReadToEnd()
Debug.WriteLine("Raw:" & rawResp)
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
Return rawResp
End Function, CancellationToken.None, _
Tasks.TaskCreationOptions.None).ContinueWith _
(Sub(task As Tasks.Task(Of String))
'Dom something with result
Console.WriteLine(task.Result)
End Sub)
Next
第一部分是数组值还是IEnumerable中的值?它是一个包含我需要翻译的文本的字符串。。通常在1到5个单词之间。您的目标是哪个版本的.NET?4.5?您可能还想使用一些来异步发出请求。谢谢!如果我理解正确,这段代码将在不阻塞的情况下并行翻译10个字符串。。对吗?不。它将是10个并行字符串(因此它将更快地完成),但它仍然会阻塞。如果不想阻止,请将Parallel.ForEach调用包装在任务中并等待。@user2452250我已将示例更改为将调用转移到线程池中的Parallel.ForEach()。我还加入了
MaxDegreeOfParallelism
功能,以确保不会不必要地淹没web请求队列。把续集连接起来,做你需要的,你就可以开始了。嘿,它工作得很好!运行所有元素大约需要2分钟!我可以使用大于10的数字,还是不建议使用?我将如何实现线程以使其非阻塞?谢谢你的帮助,真的很感激!
For Each InputString As String In myCollectionString
Tasks.Task(Of String).Factory.StartNew(Function(inputString)
Dim request As HttpWebRequest
Dim myreader As StreamReader
Dim response As HttpWebResponse
Dim rawResp As String = String.Empty
Try
Dim url As String = "http://api.mymemory.translated.net/get?q=" & inputString & "!&langpair=de|it&de=somemail@christmas.com"
request = DirectCast(WebRequest.Create(url), HttpWebRequest)
response = DirectCast(request.GetResponse(), HttpWebResponse)
myreader = New StreamReader(response.GetResponseStream())
rawResp = myreader.ReadToEnd()
Debug.WriteLine("Raw:" & rawResp)
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
Return rawResp
End Function, CancellationToken.None, _
Tasks.TaskCreationOptions.None).ContinueWith _
(Sub(task As Tasks.Task(Of String))
'Dom something with result
Console.WriteLine(task.Result)
End Sub)
Next