/// <summary>
        /// Associate the cancellation handler with the background task
        /// </summary>
        private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason, int index)
        {
            ConnectionDeferral app_dc     = null;
            ConnectionDeferral desktop_dc = null;

            lock (thisLock)
            {
                if (connectionMap.ContainsKey(index))
                {
                    app_dc = connectionMap[index];
                    connectionMap.Remove(index);
                }
                if (desktopConnectionMap.ContainsKey(index))
                {
                    desktop_dc = desktopConnectionMap[index];
                    desktopConnectionMap.Remove(index);
                }
                if (taskCompletionSourceMap.ContainsKey(index))
                {
                    taskCompletionSourceMap[index].TrySetResult(false);
                }
            }
            if (app_dc != null)
            {
                app_dc.connection.Dispose();
                app_dc.deferral.Complete();
            }
            if (desktop_dc != null)
            {
                desktop_dc.connection.Dispose();
                desktop_dc.deferral.Complete();
            }
        }
        /// <summary>
        /// Occurs when the other endpoint closes the connection to the app service
        /// </summary>
        private void OnConnectionClosed(AppServiceConnection sender, AppServiceClosedEventArgs args, int index)
        {
            ConnectionDeferral app_dc     = null;
            ConnectionDeferral desktop_dc = null;

            lock (thisLock)
            {
                if (connectionMap.ContainsKey(index))
                {
                    app_dc = connectionMap[index];
                    connectionMap.Remove(index);
                }
                if (desktopConnectionMap.ContainsKey(index))
                {
                    desktop_dc = desktopConnectionMap[index];
                    desktopConnectionMap.Remove(index);
                }
                if (taskCompletionSourceMap.ContainsKey(index))
                {
                    taskCompletionSourceMap[index].TrySetResult(false);
                }
            }
            if (app_dc != null)
            {
                app_dc.connection.Dispose();
                app_dc.deferral.Complete();
            }
            if (desktop_dc != null)
            {
                desktop_dc.connection.Dispose();
                desktop_dc.deferral.Complete();
            }
        }
        /// <summary>
        /// Receives message from Extension (via Edge)
        /// </summary>
        private async Task OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args, int index)
        {
            AppServiceDeferral messageDeferral = args.GetDeferral();

            try
            {
                TaskCompletionSource <bool> tcs = null;
                ConnectionDeferral          cd  = null;
                lock (thisLock)
                {
                    if (desktopConnectionMap.ContainsKey(index))
                    {
                        cd = desktopConnectionMap[index];
                    }
                    else
                    {
                        tcs = new TaskCompletionSource <bool>();
                        taskCompletionSourceMap.Add(index, tcs);
                    }
                }
                if (tcs != null)
                {
                    await tcs.Task;
                    lock (thisLock)
                    {
                        if (!desktopConnectionMap.ContainsKey(index))
                        {
                            return;
                        }
                        cd = desktopConnectionMap[index];
                    }
                }
                var desktopConnection = cd.connection;

                // Send message to the desktopBridge component and wait for response
                AppServiceResponse desktopResponse = await desktopConnection.SendMessageAsync(args.Request.Message);

                await args.Request.SendResponseAsync(desktopResponse.Message);
            }
            finally
            {
                messageDeferral.Complete();
            }
        }
        /// <summary>
        /// Initializes the app service on the host process
        /// </summary>
        protected async override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
        {
            base.OnBackgroundActivated(args);
            IBackgroundTaskInstance taskInstance = args.TaskInstance;

            if (taskInstance.TriggerDetails is AppServiceTriggerDetails)
            {
                var appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;

                if (appService.CallerPackageFamilyName == Windows.ApplicationModel.Package.Current.Id.FamilyName) // App service connection from desktopBridge App
                {
                    var desktopBridgeDeferral = taskInstance.GetDeferral();
                    var desktopConnection     = appService.AppServiceConnection;

                    var connectionDeferral = new ConnectionDeferral(desktopConnection, desktopBridgeDeferral);
                    int index;
                    lock (thisLock)
                    {
                        index = desktopConnectionIndex;
                        desktopConnectionIndex++;
                        desktopConnectionMap.Add(index, connectionDeferral);
                    }
                    taskInstance.Canceled += (s, a) => {
                        OnAppServicesCanceled(s, a, index);
                    };
                    desktopConnection.RequestReceived += async(s, a) => {
                        await OnDesktopAppServiceRequestReceived(s, a, index);
                    };
                    desktopConnection.ServiceClosed += (s, a) => {
                        OnConnectionClosed(s, a, index);
                    };

                    lock (thisLock)
                    {
                        if (taskCompletionSourceMap.ContainsKey(index))
                        {
                            taskCompletionSourceMap[index].TrySetResult(true);
                        }
                    }
                }
                else // App service connection from Edge browser
                {
                    // Microsoft.MicrosoftEdge_8wekyb3d8bbwe
                    var appServiceDeferral = taskInstance.GetDeferral();
                    var connection         = appService.AppServiceConnection;

                    var connectionDeferral = new ConnectionDeferral(connection, appServiceDeferral);
                    int index;
                    lock (thisLock)
                    {
                        index = connectionIndex;
                        connectionIndex++;
                        connectionMap.Add(index, connectionDeferral);
                    }

                    taskInstance.Canceled += (s, a) => {
                        OnAppServicesCanceled(s, a, index);
                    };
                    connection.RequestReceived += async(s, a) => {
                        await OnAppServiceRequestReceived(s, a, index);
                    };
                    connection.ServiceClosed += (s, a) => {
                        OnConnectionClosed(s, a, index);
                    };

                    try
                    {
                        // Make sure the tortoise_svn_opener.exe is in your AppX folder, if not rebuild the solution
                        await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
                    }
                    catch (Exception)
                    {
                        lock (thisLock)
                        {
                            if (connectionMap.ContainsKey(index))
                            {
                                connectionMap[index].connection.Dispose();
                                connectionMap[index].deferral.Complete();
                                connectionMap.Remove(index);
                            }
                            if (taskCompletionSourceMap.ContainsKey(index))
                            {
                                taskCompletionSourceMap[index].TrySetResult(false);
                            }
                        }
                    }
                }
            }
        }