在VB.NET中使用WebRequest和StreamWriter进行多线程处理

时间:2016-09-07 20:41:38

标签: vb.net multithreading streamwriter

我需要让它在线程中工作,例如,thread1使用'order_id = 1'调用url,thread2使用'order_id = 2'调用url,依此类推,然后将结果写入文件

以下是代码:

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

2 个答案:

答案 0 :(得分: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

可以通过将Web客户端创建为线程本地对象来改进此示例。这样可以避免为每次迭代创建新客户端。

答案 1 :(得分:1)

我会考虑使用微软的Reactive Framework(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,然后在完成后执行单个文件写入。