Reputation: 35
I am attempting Asyn calls but having a problem unboxing my results. Here is the error info that I got : Value of type 'System.Threading.Tasks.Task(Of String)' cannot be converted to 'String'. Can someone help to achieve this. This is my code that I used:
Private Sub Download_Click(sender As Object, e As EventArgs) Handles Button1.Click
'GET DOWNLOAD URL
Dim download_url As String = Download_HttpClient(space_id, file_id)
'ACCESS URL THROUGH GOOGLE CHROME
Dim proc As New ProcessStartInfo()
proc.FileName = "C:\Windows\System32\cmd.exe"
proc.Arguments = "/c start chrome " + download_url
Process.Start(proc)
End Sub
Public Async Function Download_HttpClient(ByVal spaceId As String, fileId As String) As Task(Of String)
Dim cookieContainer As New CookieContainer
Dim httpClientHandler As New HttpClientHandler
httpClientHandler.AllowAutoRedirect = True
httpClientHandler.UseCookies = True
httpClientHandler.CookieContainer = cookieContainer
Dim httpClient As New HttpClient(httpClientHandler)
'GET LOGIN CREDENTIALS
Dim login_url As String = host + "/common/Authentication.json"
Dim login_parameter As String = "?id=" + user_id + "&pw=" + password
Dim login_response As HttpResponseMessage = Await httpClient.GetAsync(login_url + login_parameter)
Dim login_contents As String = Await login_response.Content.ReadAsStringAsync()
'MessageBox.Show(login_contents)
'GET DOWNLOAD ID
Dim download_url As String = host + "/contentsmanagement/SingleContentsDownloadApi.json"
Dim download_param As String = "?fileId=" + file_id + "&spaceId=" + space_id + "&type=alive"
Dim download_response As HttpResponseMessage = Await httpClient.GetAsync(download_url + download_param)
Dim download_contents As String = Await download_response.Content.ReadAsStringAsync()
Dim downloadId As String = Nothing
Dim map As Dictionary(Of String, String)
map = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(download_contents)
map.TryGetValue("id", downloadId)
'MessageBox.Show(downloadId)
'set DOWNLOAD URL
Dim url As String = host + "/contentsmanagement/ContentsDownloadApi.json?id=" + downloadId
Return url
End Function
Upvotes: 1
Views: 699
Reputation: 54417
When a function is declared Async
and returns a Task(Of T)
, you need to Await
it when you call it in order to get the T
object produced by the Task
, i.e. this:
Dim download_url As String = Download_HttpClient(space_id, file_id)
needs to be changed to this:
Dim download_url As String = Await Download_HttpClient(space_id, file_id)
You can only use Await
in a method that is, itself, declared Async
though. That means that this:
Private Sub Download_Click(sender As Object, e As EventArgs) Handles Button1.Click
needs to be changed to this:
Private Async Sub Download_Click(sender As Object, e As EventArgs) Handles Button1.Click
Note that you should only ever use Async Sub
for event handlers and otherwise use Async Function
.
I would generally recommend some reading on Async
/Await
but it is a somewhat advanced topic. As a general rule, if you need to call an existing Async
function, e.g. HttpClient.GetAsync
, then you need to make your own methods Async
too.
If you have a Sub
like this:
Private Sub SomeMethod()
and you call it like this:
SomeMethod()
then that would become this:
Private Async Function SomeMethodAsync() As Task
and this:
Await SomeMethodAsync()
The exception is an event handler, which I already demonstrated above. They must be a Sub
and you don't call them directly.
Similarly, if you have a Function
like this:
Private Function SomeMethod() As T
and you call it like this:
Dim result As T = SomeMethod()
then that would become this:
Private Async Function SomeMethodAsync() As Task(Of T)
and this:
Dim result As T = Await SomeMethodAsync()
If you have a method that is not Async
and you want to call an Async
method in it, you have to make your method Async
and use Await
, then make any methods that call it Async
and use Await
in them, and on up the chain until you get to your event handler(s). This is why it is generally recommended that, if you're going to use Async
at all, you use it pretty much everywhere.
If making everything Async
is too onerous then you can call an asynchronous method synchronously and get the result of the Task
returned, e.g. this:
Dim download_url As String = Download_HttpClient(space_id, file_id)
becomes this:
Dim download_url_task As Task(Of String) = Download_HttpClient(space_id, file_id)
Dim download_url As String = download_url_task.Result
or just this:
Dim download_url As String = Download_HttpClient(space_id, file_id).Result
Upvotes: 1