Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
非阻塞webrequests vb.net_Vb.net_Multithreading_Webrequest - Fatal编程技术网

非阻塞webrequests vb.net

非阻塞webrequests vb.net,vb.net,multithreading,webrequest,Vb.net,Multithreading,Webrequest,我正在制作一个程序,必须尽快处理大约5000个字符串。其中大约2000个字符串必须通过webrequest转换到mymemory.translated.net。(请参阅下面的代码,JSON部分已删除,因为此处不需要) 代码本身工作正常,问题是它是一个阻塞代码,每个字符串大约需要1秒。我所有的琴弦都用了半个多小时。我需要将此代码转换为非阻塞代码,并同时进行多个调用。谁能告诉我怎么做?我想找一个背景工作人员,但那不会加快速度。。它只是在不同的线程上执行代码 谢谢 如果要发送10个并行请求,必须创建1

我正在制作一个程序,必须尽快处理大约5000个字符串。其中大约2000个字符串必须通过webrequest转换到mymemory.translated.net。(请参阅下面的代码,JSON部分已删除,因为此处不需要)

代码本身工作正常,问题是它是一个阻塞代码,每个字符串大约需要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