private IEnumerator ProcessEnterRoom(UserRef user, string roomName) { // Spawn new room item var go = UiHelper.AddChild(ContentPanel, ChatPanelTemplate); var chatPanel = go.GetComponent <ChatPanel>(); // Try to enter the room var observer = G.Communicator.ObserverRegistry.Create <IRoomObserver>(chatPanel); observer.GetEventDispatcher().Pending = true; observer.GetEventDispatcher().KeepingOrder = true; var t1 = user.EnterRoom(roomName, observer); yield return(t1.WaitHandle); if (t1.Status != TaskStatus.RanToCompletion) { G.Communicator.ObserverRegistry.Remove(observer); DestroyObject(go); UiMessageBox.Show("Enter room error:\n" + t1.Exception); yield break; } // Spawn new room item var occupant = (OccupantRef)t1.Result.Item1; if (occupant.IsChannelConnected() == false) { yield return(occupant.ConnectChannelAsync().WaitHandle); } chatPanel.SetOccupant(occupant); chatPanel.SetRoomInfo(t1.Result.Item2); chatPanel.ExitButtonClicked = () => OnRoomExitClick(roomName); var item = new RoomItem { ChatPanel = chatPanel, Occupant = occupant, Observer = (RoomObserver)observer, Channel = (IChannel)occupant.RequestWaiter }; _roomItemMap.Add(roomName, item); ControlPanel.AddRoomItem(roomName); observer.GetEventDispatcher().Pending = false; item.Channel.StateChanged += (_, state) => { ChannelEventDispatcher.Post(o => { if (state == ChannelStateType.Closed) { if (_roomItemMap.ContainsKey(roomName)) { OnRoomExitClick(roomName); } } }); }; // Select OnRoomItemClick(roomName); }