Как я могу отменить задачу, которая использует Continuewith? - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть задача внутри функции, это целая функция:

public async Task CreateRoom(GameTypes game)
{
    // Get the user that called this function
    User CurrentUser = ConnectedUsers.Single(r => r.Id == Context.ConnectionId);

    // Set the user name to Player 1
    CurrentUser.Name = "Player 1";

    // Add the user to a new list of Users and add that list to the Room
    UsersInRoom = new List<User>();
    UsersInRoom.Add(CurrentUser);
    Room room = new Room() { RoomName = CurrentUser.Name, Game = game, UsersInRoom = UsersInRoom };
    AllRooms.Add(room);

    // Subscribe the user to the lobby
    await Groups.AddToGroupAsync(CurrentUser.Id, CurrentUser.Name);
    CurrentUser.Room = CurrentUser.Name;

    // Send to the user that the wait screen needs to be opened
    await Clients.Caller.SendAsync("OpenWaitScreen");

    // Send to all other users to update the lobby list.
    await Clients.Others.SendAsync("ForceRoomRequest", game);

    // If in 5 minutes no user joins the lobby than send to the caller NoUsersFound
    await Task.Delay(300000).ContinueWith(async task =>
    {
        await Clients.Caller.SendAsync("NoUsersFound");
        AllRooms.Remove(room);
    });
}

Я нашел некоторые вещи в Stackoverflow, но я не знаю, как их реализовать.Но я хочу иметь возможность отменить эту задачу в другой функции.Как бы я это сделал?РЕДАКТИРОВАТЬ: это кусок кода JavaScript, который я хочу переписать на C #:

setTimeout(function (){
    socket.emit('NoUsersFound');
    delete AllRooms[data.room];
},  300000);

1 Ответ

0 голосов
/ 21 февраля 2019

Чтобы разрешить исходному потоку отменить задачу, необходимо передать токен отмены и затем пометить отмену через источник отмены.

public class Program
{
  public static void Main()
  { 
    CancellationTokenSource source = new CancellationTokenSource();
    CancellationToken token = source.Token;
    var task=AsyncMain(token);
    source.Cancel();
    try
    {
    Console.WriteLine("Main after started thread");
    task.Wait();
    Console.WriteLine("Main after task finished");
    }
    catch (AggregateException )
    {
    Console.WriteLine("Exceptions in Task");
    }
  }

  public static async Task AsyncMain(CancellationToken token)
  {
    Console.WriteLine("In Thread at Start");
    try
    {
      await Task.Delay(10).ContinueWith(
        async task =>
        {
          Console.WriteLine("Not Cancelled");
        }
        ,token);
    }
    catch(OperationCanceledException )
    {
      Console.WriteLine("Cancelled");
    }
    Console.WriteLine("In Thread after Task");
  }
}

Однако, как отметили другие люди, ContinueWith смешивает парагимы, а ненужен в этом случае.Например, вы можете сделать:

public static async Task AsyncMain(CancellationToken token)
{
    Console.WriteLine("In Thread at Start");
    await Task.Delay(10);
    if(!token.IsCancellationRequested)
    {
        //await Clients.Caller.SendAsync("NoUsersFound");
        Console.WriteLine("Not Cancelled");
    }
    else
    {
        Console.WriteLine("Cancelled");
    }
}

Или вы можете просто проверить, пуст ли список пользователей и обойти необходимость поднять отмену задачи.

...