2016-09-07 7 views
1

Мне нужно заставить его работать в потоках, например, thread1 делает вызов url с помощью 'order_id = 1', а thread2 делает вызов url с 'order_id = 2' и так и результат записывается в файл.Многопоточность с помощью WebRequest и StreamWriter в VB.NET

Вот код:

Public Sub download() 
    Dim address As String = "http://www.example.com/sales.php&order_id=" 
    Dim FILE_NAME As String = "D:\Folder\Licenses.txt" 
    Dim index As Integer = 0 

    Do While index <= 100 
      If index > 100 Then 
       Exit Do 
      End If 
     Try 
      Dim request As WebRequest = WebRequest.Create(address & index.ToString) 
      Dim response As WebResponse = request.GetResponse()     
      If CType(response, HttpWebResponse).StatusDescription = "OK" Then 
       Dim dataStream As Stream = response.GetResponseStream() 
       Dim reader As New StreamReader(dataStream) 
       Dim responseFromServer As String = reader.ReadToEnd() 
       If Not File.Exists(FILE_NAME) Then 
        Using sw As StreamWriter = File.CreateText(FILE_NAME) 
         sw.WriteLine(responseFromServer) 
         index += 1 
        End Using 
       ElseIf File.Exists(FILE_NAME) Then 
        Using sw As StreamWriter = File.AppendText(FILE_NAME) 
         sw.WriteLine(responseFromServer) 
         index += 1 
        End Using 
       End If 
      End If 
     Catch ex As Exception 
     End Try 
     Loop 
End Sub 
+0

Вам нужен выходной файл, упорядоченный по id? –

+0

Не совсем. Он должен быть сохранен в одном файле. – user41992

+0

Пожалуйста, никогда не пишите 'Catch ex As Exception' - особенно с пустым блоком catch. В противном случае появляется, что вы ** пытаетесь ** писать багги код. – Enigmativity

ответ

1

очень простой подход будет использовать Parallel.For(). Вам просто нужно убедиться, что вы не пишете разные файлы в выходной файл одновременно. Это решается с помощью Monitor, который гарантирует, что в критической секции будет только один поток. Обработка исключений опущена:

Dim address As String = "http://www.example.com/sales.php&order_id=" 
Dim FILE_NAME As String = "D:\Folder\Licenses.txt" 

Using fstream As New StreamWriter(FILE_NAME) 
    Parallel.For(0, 100, Sub(i As Integer) 
          Dim client As New WebClient 
          Dim content = client.DownloadString(address + i.ToString()) 
          Monitor.Enter(fstream) 
          fstream.WriteLine(content) 
          Monitor.Exit(fstream) 
         End Sub) 
End Using 

Этот образец может быть улучшен путем создания веб-клиентов в качестве локальных объектов. Это позволит избежать создания новых клиентов для каждой итерации.

+0

Большое вам спасибо! Он работает отлично. – user41992

1

Я бы хотел взглянуть на реактивную платформу Microsoft для этого (NuGet «System.Reactive» или «Rx-Main», чтобы получить бит).

Тогда вы можете сделать это:

Public Sub download() 

    Dim address As String = "http://www.example.com/sales.php&order_id=" 
    Dim FILE_NAME As String = "D:\Folder\Licenses.txt" 

    Dim download As Func(Of Integer, String) = _ 
     Function(n) 
      Using wc As New WebClient() 
       Return wc.DownloadString(New Uri(address & n.ToString())) 
      End Using 
     End Function 

    Dim query = _ 
     From index In Observable.Range(0, 101) _ 
     From result In Observable.Start(Function() download(index)) 
     Select New With {.Index = index, .Result = result} 

    Dim results = _ 
     query _ 
      .ToArray() _ 
      .Select(Function(xs) xs _ 
       .OrderBy(Function(x) x.Index) _ 
       .Select(Function(x) x.Result) _ 
       .ToArray()) 

    results.Do(Sub(lines) File.WriteAllLines(FILE_NAME, lines)).Wait() 

End Sub 

Это будет запрашивать каждый URL асинхронно, а затем выполнить однократном файл, когда закончите.

Смежные вопросы