Take this async function:
Public Async Function MyAsyncFunction() As Task(Of String)
Return Await SomeFunctionThatReturnsAString()
End Function
If I call it from a synchronous function like this:
Public Function MySyncFunction() As String
Return MyAsyncFunction.Result
End Function
... the function hangs.
I wondered if it is possible to write an extension like this (the extension below does not work):
Public Module TaskExtensions
<Extension()>
Public Function SyncronousResult(Of T)(aTask As Task(Of T)) As T
Dim result As T = Nothing
Task.Run(Sub()
result = aTask.Result
End Sub).Wait()
Return result
End Function
End Module
... so I could call it like this:
Public Function MySyncFunction() As String
Return MyAsyncFunction.SyncronousResult
End Function
?
CodePudding user response:
The ideal solution is not to block on asynchronous code (as I explain on my blog).
But, if you're in a situation where you literally can't use Await
(for some reason), then you can try using one of the techniques in my Brownfield Async article. Note that there is no general-purpose solution that works everywhere.
The one you suggest is blocking for the result in a thread pool thread, which may or may not work. In the example code you posted, it wouldn't work because MyAsyncFunction
has already captured the UI context and will attempt to resume in that context.
What you can try is call MyAsyncFunction
from inside a delegate passed to Task.Run
and then call GetAwaiter().GetResult()
on the returned task. That works in most cases. In my article I refer to this as the "Thread Pool Hack".