I created a simple hello world program to download data from the web.
Private Sub cmdSurf_Click(sender As Object, e As EventArgs) Handles cmdSurf.Click
Dim wb As New System.Net.WebClient
Dim uri1 = New Uri(TextBox1.Text)
Dim str = wb.DownloadString(uri1)
TextBox2.Text = str
End Sub
It's pretty simple right. I use a WebClient object to download a string syncrhonously and then I display the result in a TextBox.
Now, I want to do so asynchronously.
Basically, after I download the URI I do something else.
Then after the download is finished, I am doing what it should be.
So I did
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim wb As New System.Net.WebClient
Dim uri1 = New Uri(TextBox1.Text)
wb.DownloadStringAsync(uri1)
TextBox2.Text = ""
End Sub
It turns out DownloadStringAsync(uri1)
is a Sub, so it doesn't return anything.
So, well, what should be displayed in TextBox2 then? What am I missing?
Update: I realized that I should have used DownloadStringAsyncTask()
.
So I did this:
Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Await downloadStringAndAssignText()
TextBox2.Text = "I am downloading this. This text will change once the download is finished"
End Sub
Private Async Function downloadStringAndAssignText() As Task
Dim wb As New System.Net.WebClient
Dim uri1 = New Uri(TextBox1.Text)
Dim str = Await wb.DownloadStringTaskAsync(uri1)
TextBox2.Text = str
End Function
This is almost correct.
The thing is I want to do this properly so that
TextBox2.Text = "I am downloading this. This text will change once..."
is called BEFORE wb.DownloadStringTaskAsync(uri1)
is finished.
Also I do not want warning. So how exactly should I do that?
You can set the text of your TextBox before you call the async method that downloads the string. When Await DownloadStringAndAssignText()
is called, control will return to the calling Thread (the UI Thread), so the TextBox.Text
is set and shown.
When the async method returns, you can assign to the same TextBox the returned string value.
Your method should return a value, the string it downloaded, not assign a value to a UI element that doesn't belong to this method (its responsibility is to download a string): here the return type is set to Task(Of String)
.
You can directly assign the return value of the async method to the same TextBox.Text property.
The WebClient object should be declared with a Using
statement, so it's disposed of when the method completes.
You can directly return the result of WebClient.DownloadStringTaskAsync()
, since this method returns a string, the same return type of your method.
Imports System.Net
Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
TextBox2.Text = "I am downloading..."
TextBox2.Text = Await DownloadStringAndAssignText(TextBox1.Text)
End Sub
Private Async Function DownloadStringAndAssignText(url As String) As Task(Of String)
Using wb As New WebClient()
Return Await wb.DownloadStringTaskAsync(New Uri(url))
End Using
End Function