Beispiel #1
0
            private async Task HandshakeAsync(double minTimeoutSeconds)
            {
                using (await synchronization.LockAsync().ConfigureAwait(false)) {
                    var isServer = androidBluetoothAdapter.AdapterId.CompareTo(AdapterId) > 0;

                    // Michael's laptop is always the client as windows client doesn't understand being a server.
                    if (Name?.Contains("DESKTOP") ?? false)
                    {
                        isServer = true;
                    }

                    if (isServer)
                    {
                        socket = await inboundBluetoothSocketTable.TakeAsyncOrTimeout(device).ConfigureAwait(false);
                    }
                    else
                    {
                        var socketBox = new AsyncBox <BluetoothSocket>();
                        new Thread(() => {
                            try {
                                socketBox.SetResult(device.CreateInsecureRfcommSocketToServiceRecord(CampfireNetBluetoothConstants.APP_UUID));
                            } catch (Exception e) {
                                socketBox.SetException(e);
                            }
                        }).Start();

                        socket = await socketBox.GetResultAsync().ConfigureAwait(false);

                        var connectedChannel = ChannelFactory.Nonblocking <bool>();

                        Go(async() => {
                            await socket.ConnectAsync().ConfigureAwait(false);
                            await ChannelsExtensions.WriteAsync(connectedChannel, true);
                        }).Forget();

                        bool isTimeout = false;
                        await new Select {
                            Case(ChannelFactory.Timer(TimeSpan.FromSeconds(minTimeoutSeconds)), () => {
                                socket.Dispose();
                                isTimeout = true;
                            }),
                            Case(connectedChannel, () => {
                                // whee!
                            })
                        }.ConfigureAwait(false);
                        if (isTimeout)
                        {
                            throw new TimeoutException();
                        }
                    }
                    disconnectedChannel.SetIsClosed(false);

                    ChannelsExtensions.Go(async() => {
                        Console.WriteLine("Entered BT Reader Task");
                        var networkStream = socket.InputStream;
                        try {
                            while (!disconnectedChannel.IsClosed)
                            {
                                Console.WriteLine("Reading BT Frame");
                                var dataLengthBuffer = await ReadBytesAsync(networkStream, 4).ConfigureAwait(false);
                                var dataLength       = BitConverter.ToInt32(dataLengthBuffer, 0);
                                var data             = await ReadBytesAsync(networkStream, dataLength).ConfigureAwait(false);
                                await ChannelsExtensions.WriteAsync(inboundChannel, data).ConfigureAwait(false);
                            }
                        } catch (Exception e) {
                            Console.WriteLine(e);
                            Teardown();
                        }
                    }).Forget();
                }
            }
        private async Task ProcessCaseAsync <T>(ReadableChannel <T> channel, Func <T, Task> callback, Func <T, bool> additionalAcceptanceTest)
        {
            try {
                while (!cts.IsCancellationRequested)
                {
                    bool isFinalDispatch = false;
                    T    item;
                    try {
                        item = await channel.ReadAsync(
                            cts.Token,
                            x => {
                            if (!additionalAcceptanceTest(x))
                            {
                                return(false);
                            }
                            if (Interlocked.CompareExchange(ref dispatchesRemaining, 0, 0) == kTimesInfinite)
                            {
                                return(true);
                            }
                            else
                            {
                                var spinner = new SpinWait();
                                while (true)
                                {
                                    var capturedDispatchesRemaining = Interlocked.CompareExchange(ref dispatchesRemaining, 0, 0);
                                    var nextDispatchesRemaining     = capturedDispatchesRemaining - 1;

                                    if (nextDispatchesRemaining < 0)
                                    {
                                        return(false);
                                    }

                                    if (Interlocked.CompareExchange(ref dispatchesRemaining, nextDispatchesRemaining, capturedDispatchesRemaining) == capturedDispatchesRemaining)
                                    {
                                        isFinalDispatch = nextDispatchesRemaining == 0;
                                        return(true);
                                    }
                                    spinner.SpinOnce();
                                }
                            }
                        }).ConfigureAwait(false);
                    } catch (OperationCanceledException) {
                        //Exit processing loop - no dispatches remaining
                        break;
                    }

                    // Signal other case workers to exit
                    if (isFinalDispatch)
                    {
                        cts.Cancel();
                    }

                    // Execute callback
                    await callback(item).ConfigureAwait(false);

                    // Mark dispatcher as completed, signal awaiters
                    if (isFinalDispatch)
                    {
                        IsCompleted = true;
                        completionBox.SetResult(true);
                    }
                }
            } catch (Exception ex) {
                // Signal all other case workers to exit
                cts.Cancel();

                // Bubble all exceptions up to dispatcher awaiters
                IsCompleted = true;
                completionBox.SetException(ex);
            }
        }