首页 > 解决方案 > 如何取消使用 Continuewith 的任务?

问题描述

我在函数中有一个任务,这是整个函数:

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 上找到了一些东西,但我不知道如何实现它们。

但我希望能够在其他功能中取消此任务。
我该怎么做?

编辑:这是我想重写为 C# 的一段 javascript 代码:

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

标签: c#timeoutsignalrtask

解决方案


要允许原始线程取消任务,您需要传递取消令牌,然后通过取消源标记取消。

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 混合了 paragims,在这种情况下不需要。例如你可以这样做;

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");
    }
}

或者您可以只检查用户列表是否为空并绕过引发任务取消的需要。


推荐阅读