【问题标题】:c# Android - ISurfaceTextureListener thread interrupted then resumed when activity closedc# Android - ISurfaceTextureListener 线程中断,然后在活动关闭时恢复
【发布时间】:2017-07-31 20:09:22
【问题描述】:

我有一个带有异步 OnSurfaceTextureUpdated 方法的活动(使用 ISurfaceTextureListener),在该方法中我调用异步 SendPixel 方法:

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

这里是异步的 SendPixel 方法:

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

ISurfaceTextureListener 读取一个视频流,然后多次调用 SendPixel 方法。 问题是控制台很好地显示“SendPixel”,但不显示“SendPixelEnd”,并且没有抛出错误。 之后,当我关闭活动时,会显示每个丢失的“SendPixelEnd”。

编辑:EV3Messaging.SendMessages 发送在前几行中添加的消息(通过蓝牙):

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

为什么会发生这种情况,我该如何解决?

提前致谢。

PS:对不起我的英语不好^^

【问题讨论】:

  • 没有Ev3Messaging.SendMessages上的代码是无法确定原因的。
  • 糟糕,抱歉,我要添加它。
  • 好吧,蓝牙流似乎无法正常工作,当您关闭应用程序时关闭套接字,所有操作都结束了。您是否在连接的设备上接收消息?
  • 只接收到其中的一些(我刚刚意识到在“SendPixel”之间显示了一些“SendPixelEnd”,当然与接收到的消息相关......)。而当activity(不是app)关闭时,蓝牙设备会接收到所有发送的消息。
  • 尽量不要使用 InputStream 和 OutputStream 属性,只检索一次并在任何地方使用检索到的实例,你不知道这些属性在幕后做了什么,那些可能正在构造一个新的流每次你打电话给他们。另外,不要使用计时器来读取,创建线程或任务并连续读取,直到连接关闭。从输入流中读取不应干扰输出流。

标签: c# android multithreading asynchronous interruption


【解决方案1】:

已解决:我忘记在每次发送数据时清除 btMessage 列表,这会导致这种奇怪的行为。这个问题也可能是因为从蓝牙设备接收数据的方式不好。

那么SendMessages方法就变成了:

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

由于我每次添加消息,新的框架都会添加到 btMessage 列表的末尾。

另外,为了获取传入消息,我使用以下代码:

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

【讨论】:

    猜你喜欢
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多