Skip to content
Browse files

Fixed create client control off of ui thread triggering await hang issue

  • Loading branch information...
1 parent 804eec3 commit 683d27bf8dccd9c5a31aa5257b2cdec21121156e @Strilanc committed Jun 5, 2012
Showing with 41 additions and 23 deletions.
  1. +24 −18 Bnet/Bnet Client Component.vb
  2. +5 −1 Bnet/BnetClientControl.vb
  3. +2 −2 Bot/Bot Commands.vb
  4. +9 −1 Bot/MainBot.vb
  5. +1 −1 Interface/ClientForm.vb
View
42 Bnet/Bnet Client Component.vb
@@ -15,7 +15,7 @@ Namespace Bnet
Private ReadOnly _bot As Bot.MainBot
Private ReadOnly _name As InvariantString
Private ReadOnly _client As Bnet.Client
- Private ReadOnly _control As Control
+ Private _control As Control
Private ReadOnly _hooks As New List(Of Task(Of IDisposable))
Private ReadOnly _userGameSetMap As New Dictionary(Of BotUser, WC3.GameSet)
@@ -29,29 +29,35 @@ Namespace Bnet
Contract.Invariant(_commands IsNot Nothing)
End Sub
- Public Sub New(name As InvariantString,
- bot As Bot.MainBot,
- client As Bnet.Client)
+ Public Shared Async Function FromAsync(name As InvariantString,
+ bot As Bot.MainBot,
+ client As Bnet.Client) As Task(Of ClientComponent)
+ Dim component = New ClientComponent(name, bot, client)
+ component._control = Await BnetClientControl.FromComponentAsync(component)
+
+ Dim ct = New CancellationTokenSource()
+ component._hooks.Add(DirectCast(New DelegatedDisposable(Sub() ct.Cancel()), IDisposable).AsTask())
+ client.IncludePacketHandlerSynq(Protocol.Packets.ServerToClient.ChatEvent,
+ Function(pickle) component.OnReceivedChatEvent(pickle.Value),
+ ct.Token)
+
+ client.ChainEventualDisposalTo(component)
+ Return component
+ End Function
+ Private Sub New(name As InvariantString,
+ bot As Bot.MainBot,
+ client As Bnet.Client)
Contract.Requires(bot IsNot Nothing)
Contract.Requires(client IsNot Nothing)
Me._bot = bot
Me._name = name
Me._client = client
- Me._control = New BnetClientControl(Me)
-
- Dim ct = New CancellationTokenSource()
- Me._hooks.Add(DirectCast(New DelegatedDisposable(Sub() ct.Cancel()), IDisposable).AsTask())
- client.IncludePacketHandlerSynq(Protocol.Packets.ServerToClient.ChatEvent,
- Function(pickle) OnReceivedChatEvent(pickle.Value),
- ct.Token)
-
- client.ChainEventualDisposalTo(Me)
End Sub
- Public Shared Function FromProfile(clientName As InvariantString,
- profileName As InvariantString,
- clock As IClock,
- bot As Bot.MainBot) As ClientComponent
+ Public Shared Function FromProfileAsync(clientName As InvariantString,
+ profileName As InvariantString,
+ clock As IClock,
+ bot As Bot.MainBot) As Task(Of ClientComponent)
Contract.Requires(clock IsNot Nothing)
Contract.Requires(bot IsNot Nothing)
Contract.Ensures(Contract.Result(Of ClientComponent)() IsNot Nothing)
@@ -63,7 +69,7 @@ Namespace Bnet
Dim authenticator = Bnet.Client.MakeProductAuthenticator(profile, clock, logger)
Dim client = New Bnet.Client(profile, New CachedWC3InfoProvider, authenticator, clock, logger)
client.Init()
- Return New Bnet.ClientComponent(clientName, bot, client)
+ Return FromAsync(clientName, bot, client)
End Function
Public ReadOnly Property Client As Bnet.Client
View
6 Bnet/BnetClientControl.vb
@@ -17,7 +17,11 @@ Namespace Bnet
Contract.Invariant(_hooks IsNot Nothing)
End Sub
- Public Sub New(component As Bnet.ClientComponent)
+ Public Shared Async Function FromComponentAsync(component As Bnet.ClientComponent) As Task(Of BnetClientControl)
+ Await component.Bot.UIContext.AwaitableEntrance()
+ Return New BnetClientControl(component)
+ End Function
+ Private Sub New(component As Bnet.ClientComponent)
Contract.Assert(component IsNot Nothing)
InitializeComponent()
View
4 Bot/Bot Commands.vb
@@ -44,7 +44,7 @@ Namespace Bot.Commands
Contract.Assume(profileName IsNot Nothing)
'Contract.Ensures(Contract.Result(Of Task(Of Bnet.ClientComponent))() IsNot Nothing)
- Dim clientComponent = Bnet.ClientComponent.FromProfile(profileName, profileName, _clock, parent)
+ Dim clientComponent = Await Bnet.ClientComponent.FromProfileAsync(profileName, profileName, _clock, parent)
Try
clientComponent.QueueSetAutomatic(True)
Await parent.Components.QueueAddComponent(clientComponent)
@@ -144,7 +144,7 @@ Namespace Bot.Commands
Dim profileName = If(argument.TryGetOptionalNamedValue("profile"), "default").ToInvariant
Dim clientName = argument.RawValue(0).ToInvariant
- Dim clientComponent = Bnet.ClientComponent.FromProfile(clientName, profileName, _clock, target)
+ Dim clientComponent = Await Bnet.ClientComponent.FromProfileAsync(clientName, profileName, _clock, target)
Try
Await target.Components.QueueAddComponent(clientComponent)
If argument.HasOptionalSwitch("auto") Then clientComponent.QueueSetAutomatic(True)
View
10 Bot/MainBot.vb
@@ -26,6 +26,7 @@ Namespace Bot
Private ReadOnly _portPool As New PortPool()
Private ReadOnly _logger As Logger
Private ReadOnly _components As New ComponentSet()
+ Private ReadOnly _uiContext As SynchronizationContext
<ContractInvariantMethod()> Private Sub ObjectInvariant()
Contract.Invariant(_settings IsNot Nothing)
@@ -34,10 +35,17 @@ Namespace Bot
Contract.Invariant(_components IsNot Nothing)
End Sub
- Public Sub New(Optional logger As Logger = Nothing)
+ Public Sub New(uiContext As SynchronizationContext,
+ Optional logger As Logger = Nothing)
Me._logger = If(logger, New Logger)
+ Me._uiContext = uiContext
End Sub
+ Public ReadOnly Property UIContext As SynchronizationContext
+ Get
+ Return _uiContext
+ End Get
+ End Property
Public ReadOnly Property PortPool As PortPool
Get
Contract.Ensures(Contract.Result(Of PortPool)() IsNot Nothing)
View
2 Interface/ClientForm.vb
@@ -36,7 +36,7 @@ Public Class ClientForm
Contract.Requires(_bot Is Nothing)
Contract.Ensures(_bot IsNot Nothing)
- _bot = New Bot.MainBot()
+ _bot = New Bot.MainBot(SynchronizationContext.Current)
_bot.Components.QueueAddComponent(New Bot.MainBotManager(_bot))
Bot.IncludeBasicBotCommands(_bot, clock)
Bot.IncludeBasicBnetClientCommands(_bot)

0 comments on commit 683d27b

Please sign in to comment.
Something went wrong with that request. Please try again.