public async Task JoinRoom(Room room) { var cancellationSource = joinCancellationSource = new CancellationTokenSource(); await joinOrLeaveTaskChain.Add(async() => { if (Room != null) { throw new InvalidOperationException("Cannot join a multiplayer room while already in one."); } Debug.Assert(room.RoomID.Value != null); // Join the server-side room. var joinedRoom = await JoinRoom(room.RoomID.Value.Value).ConfigureAwait(false); Debug.Assert(joinedRoom != null); // Populate users. Debug.Assert(joinedRoom.Users != null); await Task.WhenAll(joinedRoom.Users.Select(PopulateUser)).ConfigureAwait(false); // Update the stored room (must be done on update thread for thread-safety). await scheduleAsync(() => { Room = joinedRoom; apiRoom = room; defaultPlaylistItemId = apiRoom.Playlist.FirstOrDefault()?.ID ?? 0; }, cancellationSource.Token).ConfigureAwait(false); // Update room settings. await updateLocalRoomSettings(joinedRoom.Settings, cancellationSource.Token).ConfigureAwait(false); }, cancellationSource.Token).ConfigureAwait(false); }
/// <summary> /// Joins the <see cref="MultiplayerRoom"/> for a given API <see cref="Room"/>. /// </summary> /// <param name="room">The API <see cref="Room"/>.</param> /// <param name="password">An optional password to use for the join operation.</param> public async Task JoinRoom(Room room, string?password = null) { if (Room != null) { throw new InvalidOperationException("Cannot join a multiplayer room while already in one."); } var cancellationSource = joinCancellationSource = new CancellationTokenSource(); await joinOrLeaveTaskChain.Add(async() => { Debug.Assert(room.RoomID.Value != null); // Join the server-side room. var joinedRoom = await JoinRoom(room.RoomID.Value.Value, password ?? room.Password.Value).ConfigureAwait(false); Debug.Assert(joinedRoom != null); // Populate users. Debug.Assert(joinedRoom.Users != null); await Task.WhenAll(joinedRoom.Users.Select(PopulateUser)).ConfigureAwait(false); // Update the stored room (must be done on update thread for thread-safety). await runOnUpdateThreadAsync(() => { Debug.Assert(Room == null); Room = joinedRoom; APIRoom = room; Debug.Assert(joinedRoom.Playlist.Count > 0); APIRoom.Playlist.Clear(); APIRoom.Playlist.AddRange(joinedRoom.Playlist.Select(createPlaylistItem)); APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == joinedRoom.Settings.PlaylistItemId); Debug.Assert(LocalUser != null); addUserToAPIRoom(LocalUser); foreach (var user in joinedRoom.Users) { updateUserPlayingState(user.UserID, user.State); } updateLocalRoomSettings(joinedRoom.Settings); OnRoomJoined(); }, cancellationSource.Token).ConfigureAwait(false); }, cancellationSource.Token).ConfigureAwait(false); }
public async Task TestChainedTaskDoesNotCompleteBeforeChildTasks() { var mutex = new ManualResetEventSlim(false); var task = taskChain.Add(async() => await Task.Run(() => mutex.Wait(globalCancellationToken.Token))); // Allow task to potentially complete Thread.Sleep(1000); Assert.That(task.IsCompleted, Is.False); // Allow the task to complete. mutex.Set(); await task; }
public async Task JoinRoom(Room room, string?password = null) { var cancellationSource = joinCancellationSource = new CancellationTokenSource(); await joinOrLeaveTaskChain.Add(async() => { if (Room != null) { throw new InvalidOperationException("Cannot join a multiplayer room while already in one."); } Debug.Assert(room.RoomID.Value != null); // Join the server-side room. var joinedRoom = await JoinRoom(room.RoomID.Value.Value, password ?? room.Password.Value).ConfigureAwait(false); Debug.Assert(joinedRoom != null); // Populate users. Debug.Assert(joinedRoom.Users != null); await Task.WhenAll(joinedRoom.Users.Select(PopulateUser)).ConfigureAwait(false); // Update the stored room (must be done on update thread for thread-safety). await scheduleAsync(() => { Room = joinedRoom; APIRoom = room; Debug.Assert(LocalUser != null); addUserToAPIRoom(LocalUser); foreach (var user in joinedRoom.Users) { updateUserPlayingState(user.UserID, user.State); } OnRoomJoined(); }, cancellationSource.Token).ConfigureAwait(false); // Update room settings. await updateLocalRoomSettings(joinedRoom.Settings, cancellationSource.Token).ConfigureAwait(false); }, cancellationSource.Token).ConfigureAwait(false); }