Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Unable to Cancel Socket.ReceiveAsync with CancellationTokenSource in Unity (Unity version: 2022.3.26

Discussion in 'Scripting' started by bbsuuo, May 10, 2024.

  1. bbsuuo

    bbsuuo

    Joined:
    Jul 21, 2016
    Posts:
    19
    I've been experimenting with asynchronous programming in Unity for handling network communication recently, but I've encountered a tricky issue. I'm using the asynchronous method Socket.ReceiveAsync to receive data and I want to be able to cancel this operation using a CancellationTokenSource. However, no matter what I try, I can't seem to cancel the ReceiveAsync operation successfully.

    Here's a simplified version of my code:

    Code (CSharp):
    1. private async void Start()
    2. {
    3.     IPAddress ipAddress = IPAddress.Parse(ip);
    4.     IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port);
    5.  
    6.     var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    7.     Memory<byte> test = new Memory<byte>(new byte[2048]);
    8.     var tokenSource = new CancellationTokenSource();
    9.  
    10.     InputSystem.onAnyButtonPress.Call(x =>
    11.     {
    12.         if (x is KeyControl keyboardCtl && keyboardCtl.keyCode == Key.E)
    13.         {
    14.             tokenSource.Cancel();
    15.             Debug.Log("token cancel");
    16.         }
    17.     });
    18.  
    19.     Debug.Log("start receive");
    20.     try
    21.     {
    22.         int count = await socket.ReceiveAsync(test, SocketFlags.None, tokenSource.Token);
    23.         Debug.Log($"end receive : {count}");
    24.     }
    25.     catch (OperationCanceledException)
    26.     {
    27.         Debug.Log("ReceiveAsync cancelled");
    28.     }
    29. }
    30.  
    In this code snippet, I expect the ReceiveAsync operation to be cancelled when a certain button (e.g., the E key on the keyboard) is pressed. However, no matter what I try, I can't seem to trigger the cancellation operation.

    I suspect the issue may lie with the Socket.ReceiveAsync method, as it doesn't seem to respond to the CancellationTokenSource passed to it. I expect the ReceiveAsync method to throw an OperationCanceledException when the cancellation token is triggered, but instead, it continues to block the thread
     
  2. bbsuuo

    bbsuuo

    Joined:
    Jul 21, 2016
    Posts:
    19
    I discovered that I can indeed cancel the ReceiveAsync operation using the following approach:
    Code (CSharp):
    1. int count = await socket.ReceiveAsync(test, SocketFlags.None, tokenSource.Token)
    2.                     .AsUniTask<int>()
    3.                     .AttachExternalCancellation(tokenSource.Token);
    4.  
    However, upon further consideration, I believe this approach may introduce some implicit issues. Using AttachExternalCancellation seems to work, but it feels like a workaround rather than a clean solution.
     
    Last edited: May 10, 2024
  3. Alex-Thibodeau

    Alex-Thibodeau

    Unity Technologies

    Joined:
    Apr 18, 2013
    Posts:
    43
    Have you tried your code with a regular dotnet framework application? In general if it works there but not in Unity it is a bug that we should investigate.