Talking back to the interface using Delegates and Events in VB.NET

I love using Async and Await. It makes asynchronous programming so much easier. One area I have never really liked though is the functionality for talking back to the main thread (like the UI thread) when you are doing asynchronous things though. Something I have started doing recently (and for some reason had lost from my toolbox of techniques) is the use of Delegates and Events. In the class that has a method that runs asynchronously, I delcare some public events. These events can then be tied up on the UI thread. Then when the event is raised in the asynchronous method, the call is made back to the UI thread and it has the correct context. I haven't looked in depth into how this achieved but it works very well and gives the class with the async method on it a lot of flexbility as it's not tied to the calling class in anyway.
Imports System.Data.SqlClient
Module Updater
Sub Main()
Console.WriteLine("Welcome to the cool async updater")
dim updater = New DatabaseUpdater(new UpdateScanner())
addHandler updater.ErrorRaised, AddressOf InformUserOfError
AddHandler Updater.Success, AddressOf InformUserOfSuccess
dim updaterRun = Task.Factory.StartNew(Async Sub() Await updater.Run())
updaterRun.Wait()
Console.ReadKey()
End Sub
Private Sub InformUserOfSuccess(eventdetails As ExecutionResult)
Dim color = console.BackgroundColor
If eventdetails.Success then
Console.ForegroundColor = ConsoleColor.Green
Console.WriteLine("You did it! Teh Updates ran")
Console.WriteLine(eventdetails.Message)
Else
Console.ForegroundColor = ConsoleColor.Yellow
Console.WriteLine("Oh man there were problems")
Console.WriteLine(eventdetails.Message)
End If
Console.ForegroundColor = color
End Sub
Private Sub InformUserOfError(eventdetails As ExecutionResult)
dim color = console.ForegroundColor
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine("{0}, {1}", eventdetails.Message, eventdetails.Exception.Message)
Console.ForegroundColor = color
End Sub
End Module
public delegate sub SuccessEvent(eventDetails As ExecutionResult)
Public Delegate Sub ErrorEvent(eventDetails as ExecutionREsult)
Public Class DatabaseUpdater
public Event Success as SuccessEvent
public Event ErrorRaised as ErrorEvent
Private ReadOnly _updateScanner As IUpdateScanner
public Sub New (updateScanner As IUpdateScanner)
Me._updateScanner = updateScanner
end Sub
public Async function Run() As Task
Dim updates = Me._updateScanner.Updates().ToArray()
dim failed as Integer
If updates.Any() then
try
Using conn as New SqlConnection("")
await conn.OpenAsync()
for each u in updates
dim result = Await Update(u, conn)
If result = false
failed = failed + 1
End If
Next
conn.Close()
End Using
Catch ex As Exception
RaiseEvent ErrorRaised(New ExecutionResult(false, "Unable to create the connection", ex))
return
End Try
End If
RaiseEvent Success(new ExecutionResult(failed = 0, $"{updates.Count() - failed} of {updates.Count()} Updates completed successfully", nothing))
End function
Async Function Update(updateCommand As string, conn As SqlConnection) as Task(Of boolean)
Try
Using command As New SqlCommand(updateCommand, conn)
command.CommandType = CommandType.Text
Await command.ExecuteNonQueryAsync()
End Using
Catch ex As Exception
RaiseEvent ErrorRaised(new ExecutionResult(False, $"There was an error running the update `{updateCommand}`", ex))
return false
End Try
return true
End Function
End Class
Public Class ExecutionResult
Property Success() As boolean
Property Message() As string
Property Exception() As Exception
Public sub New(success As Boolean, message As String, exception As Exception)
me.Success = success
me.Message = message
me.Exception = exception
End sub
End Class
public Interface IUpdateScanner
function Updates() As IEnumerable(of string)
End Interface
Public Class UpdateScanner
Implements IUpdateScanner
Public Function Updates() As IEnumerable(Of String) Implements IUpdateScanner.Updates
Dim list = New List(Of String)()
list.Add("CREATE TABLE [dbo].[Pet](
[Type] [int] NULL
) ON [PRIMARY]")
list.Add("CREATE TABLE [dbo].[Pie](
[Type] [int] NULL
) ON [PRIMARY]")
Return list
End Function
End Class
view raw Updater.vb hosted with ❤ by GitHub
SHARE

Dom Finn

  • Image
  • Image
  • Image
  • Image
  • Image
    Blogger Comment
    Facebook Comment

0 comments:

Post a Comment