private async void btnChat_Click(object sender, EventArgs e) { if (lstPeers.SelectedIndex == -1) { MessageBox.Show("Please select a peer."); return; } Peer remotePeer = Peer.CreateFromString(lstPeers.GetItemText(lstPeers.SelectedItem)); _httpSignaler.SendToPeer(remotePeer.Id, "OpenDataChannel"); await SetupPeer(remotePeer, true); }
private async Task SetupPeer(Peer remotePeer, bool isInitiator) { var found = lstPeers.FindString(remotePeer.ToString()); if (ListBox.NoMatches != found) { remotePeer = Peer.CreateFromString(lstPeers.GetItemText(lstPeers.Items[found])); } Tuple <OrtcController, ChatForm> tuple; if (_chatSessions.TryGetValue(remotePeer.Id, out tuple)) { // already have a form created tuple.Item2.HandleRemotePeerDisconnected(); tuple.Item2.BringToFront(); tuple.Item1.Dispose(); _chatSessions.Remove(remotePeer.Id); } else { if (!Properties.Settings.Default.MultipleConnections) { if (_chatSessions.Count > 0) { // Clear out existing chat forms as only one chat form // is allowed. DisposeChatForms(); } } // no chat form created, spawn a new one tuple = new Tuple <OrtcController, ChatForm>(null, new ChatForm(OrtcController.LocalPeer, remotePeer)); tuple.Item2.SendMessageToRemotePeer += ChatForm_SendMessageToRemotePeer; // Invoking .ShowDialog() would block the signaler's task // being waited upon. Show() block the current task // from continuing until the dialog is dismissed but does // not block other events from processing on the GUI // thread. Not blocking events is insufficient though. The // task is waited by the signaler to complete before the // next signaler message from the server is allowed to be // processed so a dialog cannot be spawned from within the // processing of a peer's message task. // // The solution though to the blocking of the signaler's // task when bringing up a dialog is rather simple: invoke // the .ShowDialog() method asynchronously on the GUI // thread and not from within the current signaler message // task. This allows the GUI to be displayed and events are // processed as normal including other signaler messages // from peers. BeginInvoke((Action)(() => { if (Properties.Settings.Default.MultipleConnections) { // show the form non model tuple.Item2.Show(); } else { // invoke this on the main thread without blocking the // current thread from continuing tuple.Item2.ShowDialog(); } })); } // create a new tuple and carry forward the chat form from the previous tuple tuple = new Tuple <OrtcController, ChatForm>(new OrtcController(remotePeer, isInitiator), tuple.Item2); _chatSessions.Add(remotePeer.Id, tuple); tuple.Item1.DataChannelConnected += OrtcSignaler_OnDataChannelConnected; tuple.Item1.DataChannelDisconnected += OrtcSignaler_OnDataChannelDisconnected; tuple.Item1.SignalMessageToPeer += OrtcSignaler_OnSignalMessageToPeer; tuple.Item1.DataChannelMessage += OrtcSignaler_OnDataChannelMessage; await tuple.Item1.SetupAsync(); }