Как я могу отменить LoadAsync (), не закрывая основной сокет? - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть приложение, которое связывается с некоторыми устройствами через rfcomm по Bluetooth.Мое приложение работает на Android и работает над UWP.Вот как я настраиваю средства чтения / записи потоков в коде UWP:

var btDevice = await BluetoothDevice.FromIdAsync(devId);

var services = await btDevice.GetRfcommServicesAsync();

if (services.Services.Count > 0)
{
    // We only have one service so use the first one...
    var service = services.Services[0];
    // Create a stream...
    _bluetoothStream = new StreamSocket();
    await _bluetoothStream.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);

    _dataReader = new DataReader(_bluetoothStream.InputStream);
    _dataWriter = new DataWriter(_bluetoothStream.OutputStream);

    _dataReader.InputStreamOptions = InputStreamOptions.Partial;

Мое оборудование отправляет данные в мое приложение только после того, как приложение отправляет данные, поэтому я настроил механизм отправки / получения.Все работает отлично, за исключением конкретного случая использования, когда мое устройство перезагружается (но соединение Bluetooth все еще активно) и не может отправить ответ.В этом случае мой код верхнего уровня настроен на попытку повторной попытки, однако соединение Bluetooth закрывается, когда время ожидания истекло.

_dataWriter.WriteBytes(comm.TransmitData);

Task<UInt32> writeAysncTask = _dataWriter.StoreAsync().AsTask();

UInt32 bytesWritten = await writeAysncTask;
:
try
{
    using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(comm.TimeoutMs))) // _receiveTimeoutMs)))
    {
        // When this times out, exception gets thrown and socket is closed
        // How do I prevent the socket from closing so I can do a retry???
        var loadTask = _dataReader.LoadAsync(comm.ReceiveCount).AsTask(cts.Token);

        bytesRead = await loadTask;

        if (bytesRead > 0)
        {
            rxData = new byte[bytesRead];
            _dataReader.ReadBytes(rxData);
        }
        else
        {
            System.Diagnostics.Debug.WriteLine("Received 0!");
        }
    }
}
catch (Exception ex)
{
    // The bluetooth connection is closed automatically if the
    // caancellationToken fires...In my case, I need the connection
    // to stay open...How do I achieve this???


    // Update: When this code is executed with _dataReader/Writer
    // that was created with SerialDevice class (see below), the
    // timeout exception does not cause the Serial connection to
    // close so my calling code can then issue a retry.
    System.Diagnostics.Debug.WriteLine(ex.Message) ;
}

ОБНОВЛЕНИЕ: Следует отметить, что когда я использую точно такой же код с потоками, созданными из SerialDevice, все работает так, как я ожидал ... Когда время приема сокета НЕ закрыто.Похоже, я столкнулся с чем-то в реализации Bluetooth в UWP.Тьфу.Вот как я могу создать _dataReader / _dataWriter с классом SerialDevice:

_serialDevice = await SerialDevice.FromIdAsync(devId);
// Configure the port
_serialDevice.BaudRate = _baudrate;
_serialDevice.Parity = SerialParity.None;
_serialDevice.DataBits = 8;
_serialDevice.StopBits = SerialStopBitCount.One;

_dataReader = new DataReader(_serialDevice.InputStream);
_dataWriter = new DataWriter(_serialDevice.OutputStream);
...