Microsoft.R.Host.Client.RHost.RunLoop C# (CSharp) Method

RunLoop() private method

private RunLoop ( CancellationToken loopCt ) : Task
loopCt System.Threading.CancellationToken
return Task
        private async Task<Message> RunLoop(CancellationToken loopCt) {
            TaskUtilities.AssertIsOnBackgroundThread();
            var cancelAllCtsLink = CancellationTokenSource.CreateLinkedTokenSource(loopCt, _cancelAllCts.Token);
            var ct = cancelAllCtsLink.Token;
            try {
                _log.EnterRLoop(_rLoopDepth++);
                while (!loopCt.IsCancellationRequested) {
                    var message = await ReceiveMessageAsync(loopCt);
                    if (message == null) {
                        return null;
                    } else if (message.IsResponse) {
                        Request request;
                        if (!_requests.TryRemove(message.RequestId, out request)) {
                            throw ProtocolError($"Mismatched response - no request with such ID:", message);
                        } else if (message.Name != ":" + request.MessageName.Substring(1)) {
                            throw ProtocolError($"Mismatched response - message name does not match request '{request.MessageName}':", message);
                        }

                        request.Handle(this, message);
                        continue;
                    }

                    try {
                        switch (message.Name) {
                            case "!End":
                                message.ExpectArguments(1);
                                await _callbacks.Shutdown(message.GetBoolean(0, "rdataSaved"));
                                break;

                            case "!CanceledAll":
                                CancelAll();
                                break;

                            case "?YesNoCancel":
                                ShowDialog(message, MessageButtons.YesNoCancel, ct)
                                    .SilenceException<MessageTransportException>()
                                    .DoNotWait();
                                break;

                            case "?YesNo":
                                ShowDialog(message, MessageButtons.YesNo, ct)
                                    .SilenceException<MessageTransportException>()
                                    .DoNotWait();
                                break;

                            case "?OkCancel":
                                ShowDialog(message, MessageButtons.OKCancel, ct)
                                    .SilenceException<MessageTransportException>()
                                    .DoNotWait();
                                break;

                            case "?>":
                                ReadConsole(message, ct)
                                    .SilenceException<MessageTransportException>()
                                    .DoNotWait();
                                break;

                            case "!":
                            case "!!":
                                message.ExpectArguments(1);
                                await _callbacks.WriteConsoleEx(
                                    message.GetString(0, "buf", allowNull: true),
                                    message.Name.Length == 1 ? OutputType.Output : OutputType.Error,
                                    ct);
                                break;

                            case "!ShowMessage":
                                message.ExpectArguments(1);
                                await _callbacks.ShowMessage(message.GetString(0, "s", allowNull: true), ct);
                                break;

                            case "!+":
                                await _callbacks.Busy(true, ct);
                                break;
                            case "!-":
                                await _callbacks.Busy(false, ct);
                                break;

                            case "!SetWD":
                                _callbacks.DirectoryChanged();
                                break;

                            case "!Library":
                                await _callbacks.ViewLibrary(ct);
                                break;

                            case "!ShowFile":
                                message.ExpectArguments(3);
                                // Do not await since it blocks callback from calling the host again
                                _callbacks.ShowFile(
                                    message.GetString(0, "file"),
                                    message.GetString(1, "tabName"),
                                    message.GetBoolean(2, "delete.file"),
                                    ct).DoNotWait();
                                break;

                            case "!View":
                                message.ExpectArguments(2);
                                _callbacks.ViewObject(message.GetString(0, "x"), message.GetString(1, "title"), ct)
                                    .SilenceException<MessageTransportException>()
                                    .DoNotWait();
                                break;

                            case "!Plot":
                                await _callbacks.Plot(
                                    new PlotMessage(
                                        Guid.Parse(message.GetString(0, "device_id")),
                                        Guid.Parse(message.GetString(1, "plot_id")),
                                        message.GetString(2, "file_path"),
                                        message.GetInt32(3, "device_num"),
                                        message.GetInt32(4, "active_plot_index"),
                                        message.GetInt32(5, "plot_count"),
                                        message.Blob),
                                    ct);
                                break;

                            case "?Locator":
                                var locatorResult = await _callbacks.Locator(Guid.Parse(message.GetString(0, "device_id")), ct);
                                ct.ThrowIfCancellationRequested();
                                await RespondAsync(message, ct, locatorResult.Clicked, locatorResult.X, locatorResult.Y);
                                break;

                            case "?PlotDeviceCreate":
                                var plotDeviceResult = await _callbacks.PlotDeviceCreate(Guid.Parse(message.GetString(0, "device_id")), ct);
                                ct.ThrowIfCancellationRequested();
                                await RespondAsync(message, ct, plotDeviceResult.Width, plotDeviceResult.Height, plotDeviceResult.Resolution);
                                break;

                            case "!PlotDeviceDestroy":
                                await _callbacks.PlotDeviceDestroy(Guid.Parse(message.GetString(0, "device_id")), ct);
                                break;

                            case "!WebBrowser":
                                _callbacks.WebBrowser(message.GetString(0, "url"), ct)
                                    .DoNotWait();
                                break;

                            case "!PackagesInstalled":
                                _callbacks.PackagesInstalled();
                                break;

                            case "!PackagesRemoved":
                                _callbacks.PackagesRemoved();
                                break;
                            case "!FetchFile":
                                var remoteFileName = message.GetString(0, "file_remote_name");
                                var localPath = message.GetString(1, "file_local_path");
                                var destPath = await _callbacks.SaveFileAsync(remoteFileName, localPath, message.Blob, ct);
                                if (!message.GetBoolean(2, "silent")) {
                                    await _callbacks.WriteConsoleEx(destPath, OutputType.Error, ct);
                                }
                                break;
                            default:
                                throw ProtocolError($"Unrecognized host message name:", message);
                        }

                        if (_cancelAllCts.IsCancellationRequested) {
                            ct = UpdateCancelAllCtsLink(ref cancelAllCtsLink, loopCt);
                        }
                    } catch (OperationCanceledException) when (_cancelAllCts.IsCancellationRequested) {
                        // Canceled via _cancelAllCts - update cancelAllCtsLink and move on
                        ct = UpdateCancelAllCtsLink(ref cancelAllCtsLink, loopCt);
                    }
                }
            } finally {
                // asyncronously-running handlers like ReadConsole and ShowDialog that were started in the loop should be canceled
                cancelAllCtsLink.Cancel();
                cancelAllCtsLink.Dispose();
                _log.ExitRLoop(--_rLoopDepth);
            }

            return null;
        }