Search code examples
c#androidmultithreadingasynchronousinterruption

c# Android - ISurfaceTextureListener thread interrupted then resumed when activity closed


I have an activity (with an ISurfaceTextureListener) with an async OnSurfaceTextureUpdated method in which I call the async SendPixel method:

public async void OnSurfaceTextureUpdated(SurfaceTexture surface)
{
    bool sendPixel = false;

    [...]

    if (Settings.Pixel.period >= 0)
    {
        if (stopWatch.ElapsedMilliseconds >= Settings.Pixel.nextSending)
        {
            if (Settings.Pixel.period > 0)
                Settings.Pixel.nextSending += Settings.Pixel.period * ((int)((stopWatch.ElapsedMilliseconds - Settings.Pixel.nextSending) / Settings.Pixel.period) + 1);
            sendPixel = true;
        }
    }

    [...]

    if (sendPixel)
        await SendPixel();
}

Here is the async SendPixel method:

async Task SendPixel()
{
    try
    {
        if (Ev3Messaging.IsConnected())
        {
            Color color = new Color(bm.GetPixel(Settings.Camera.viewport.X_VpToCv(Settings.Pixel.x), Settings.Camera.viewport.X_VpToCv(Settings.Pixel.y)));
            Ev3Messaging.AddNumberMessage("MC_Hue", color.GetHue());
            Ev3Messaging.AddNumberMessage("MC_Brightness", color.GetBrightness());
            Console.WriteLine("SendPixel");
            await Ev3Messaging.SendMessages();
            Console.WriteLine("SendPixelEnd");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error SendPixel: " + ex.Message);
    }
}

The ISurfaceTextureListener reads a video stream, then the SendPixel method is called many times. The issue is that the console well displays "SendPixel", but doesn't display "SendPixelEnd", and no error is thrown. Afterwards, when I close the activity, every missing "SendPixelEnd" are displayed.

EDIT: The EV3Messaging.SendMessages sends the messages (by Bluetooth) added in the previous lines:

static List<byte> btMessage = new List<byte>();
static public async Task SendMessages()
{
    if (_socket != null)
        await _socket.OutputStream.WriteAsync(btMessage.ToArray(), 0, btMessage.Count);
}

Why does that happen and how can I solve that ?

Thanks in advance.

PS: Sorry for my poor English ^^


Solution

  • SOLVED: I have forgotten to clear the btMessage List each time I send the data, then this results in this strange behaviour. This issue may also be because of the bad way used to receive data from the Bluetooth device.

    Then the SendMessages method becomes:

    static public async Task SendMessages()
    {
        if (_socket != null)
            await _socket.OutputStream.WriteAsync(btMessage.ToArray(), 0, btMessage.Count);
        btMessage.Clear();
    }
    

    since each time I add a message, the new frame is added at the end of the btMessage List.

    Also, to get the incoming message, I use this code:

    public static void InputMessagesManager(Action<BtMessage> incomingMessageEvent)
    {
        _tokenSource = new CancellationTokenSource();
        Task t = Task.Factory.StartNew(async () =>
        {
            Stream inputStream = _socket.InputStream;
    
            while (!_tokenSource.IsCancellationRequested)
            {
                if (inputStream == null)
                    inputStream = _socket.InputStream;
                if (inputStream != null && inputStream.CanRead)
                {
                    await inputStream.ReadAsync(_sizeBuffer, 0, _sizeBuffer.Length);
    
                    short size = (short)(_sizeBuffer[0] | _sizeBuffer[1] << 8);
                    if (size != 0)
                    {
                        byte[] frame = new byte[size];
                        await inputStream.ReadAsync(frame, 0, frame.Length);
                        BtMessage btMes = new BtMessage(frame);
                        incomingMessageEvent(btMes);
                        Console.WriteLine("Received: " + btMes.name + " -> " + btMes.getValueAsNumber());
                    }
                }
            }
        }, _tokenSource2.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current);
    }