【问题标题】:UWP AppServiceConnection - SendResponseAsync returns AppServiceResponseStatus.FailureUWP AppServiceConnection - SendResponseAsync 返回 AppServiceResponseStatus.Failure
【发布时间】:2020-09-29 11:06:49
【问题描述】:

我正在尝试在 Raspberry Pi3 上创建一个 UWP 服务应用程序,它提供对板载 UART 的访问。我遇到了有关 AppConnection 请求/响应的问题。

这是处理来自客户端应用程序的传入请求的服务方法

internal class Inbound
{
    public static async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var messageDeferral = args.GetDeferral();
        var response = new ValueSet();

        bool success = false;
        var msg = args.Request.Message.Keys;
        if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.Command, out object command))
        {
            try
            {
                switch (command)
                {

                    case ServiceApiRequests.CommandValues.UartWrite:
                        if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.UartTxBuffer, out object txBuffer))
                        {
                            string rxBuff = "";
                            success = await Pi3.Peripherals.Uart.GerInstance(57600).Write((string)txBuffer);

                            if (success)
                            {
                                Debug.WriteLine("Tx: " + (string)txBuffer);
                                if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.ReadUartResponse, out object getResponse))
                                {
                                    if ((string)getResponse == ServiceApiRequests.ReadUartResponse.Yes)
                                    {
                                        rxBuff = await Pi3.Peripherals.Uart.GerInstance(57600).Read();
                                        Debug.WriteLine("Rx: " + rxBuff);
                                    }
                                }
                            }
                            response.Add(ServiceApiRequests.Keys.UartRxBuffer, rxBuff);

                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
            }
        }

        response.Add(new KeyValuePair<string, object>(ServiceApiRequests.Keys.Result, success ? ServiceApiRequests.ResultValues.Ok : ServiceApiRequests.ResultValues.Ko));
        var result = await args.Request.SendResponseAsync(response);
        if (result == AppServiceResponseStatus.Failure)
        {
            Debug.WriteLine("Failed to send the response");
        }
        messageDeferral.Complete();
    }
}

如您所见,Uart 类是使用方法Pi3.Peripherals.Uart.GerInstance(57600) 使用单例模式获取的。

按照我用于从客户端应用程序发送请求的代码。

    public static class Uart
{
    public static IAsyncOperation<string> SendCommand(this AppServiceConnection DriverControllerConnection, string txBuffer, string awaitResponse = ServiceApiRequests.ReadUartResponse.Yes)
    {
        return _SendCommand(DriverControllerConnection, txBuffer, awaitResponse).AsAsyncOperation();
    }
    private static async Task<string> _SendCommand(AppServiceConnection DriverControllerConnection, string txBuffer, string awaitResponse)
    {
        AppServiceResponse response = null;
        string response_str = "";
        try
        {
            if (DriverControllerConnection != null)
            {
                response = await DriverControllerConnection.SendMessageAsync(new ServiceApiRequests.UartWrite().GetCommand(txBuffer, awaitResponse));
                if (response.Status == AppServiceResponseStatus.Success)
                {
                    if (response.Message.TryGetValue(ServiceApiRequests.Keys.Result, out object result))
                    {
                        if ((string)result == ServiceApiRequests.ResultValues.Ok && awaitResponse == ServiceApiRequests.ReadUartResponse.Yes)
                        {
                            response_str = response.Message[ServiceApiRequests.Keys.UartRxBuffer] as string;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // TODO: log
        }
        return response_str;
    }
}

系统运行良好一段时间,直到我有response.Status == AppServiceResponseStatus.Success,然后请求的结果发生变化,它变成AppServiceResponseStatus.Failure。这样程序计数器就不会进入条件if (response.Status == AppServiceResponseStatus.Success)

知道原因吗? 非常感谢您的帮助。

编辑

按照建议,我为ServiceClosed 事件添加了一个处理程序。这是主类。

public sealed class DriverListener : IBackgroundTask
{
    private BackgroundTaskDeferral backgroundTaskDeferral;
    private AppServiceConnection appServiceConnection;
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        backgroundTaskDeferral = taskInstance.GetDeferral();
        // taskInstance.Canceled += OnTaskCanceled;

        var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails;
        appServiceConnection = triggerDetails.AppServiceConnection;
        appServiceConnection.RequestReceived += Inbound.OnRequestReceived;
        appServiceConnection.ServiceClosed += OnTaskCanceled;
    }

    private void OnTaskCanceled(AppServiceConnection sender, AppServiceClosedEventArgs reason)
    {
        if (this.backgroundTaskDeferral != null)
        {
            Debug.WriteLine("ServiceClosed");
            // Complete the service deferral.
            this.backgroundTaskDeferral.Complete();
        }
    }
}

在这个函数中放置一个断点,我发现它从未被触发。 应用程序连接使用单例模式打开,并放入我在客户端应用程序中使用的 dll 中

    public static AppServiceConnection GetDriverConnectionInstance()
    {
        if (_DriverConnectionInstance == null)
        {
            try
            {
                _DriverConnectionInstance = OpenDriverConnection().AsTask().GetAwaiter().GetResult();
            }
            catch
            {

            }
        }
        return _DriverConnectionInstance;   
    }

我还向服务添加了一个切换 LED 的请求,我注意到 LED 状态发生了变化,但来自应用服务的响应仍然是“失败”并且消息为空。

【问题讨论】:

  • 几个问题来澄清场景:1)您的客户端应用程序也是在同一设备上运行的 UWP 应用程序吗? 2) ServicedClosed 事件是否在您的 AppServiceConnection 上触发?
  • 您好@StefanWickMSFT,感谢您的回复:1) 是的,它是在同一个 RPi3 上运行的后台服务。 2) 不,这是我第一次听说。我该如何使用它?

标签: c# uwp windows-10 iot windows-10-iot-core


【解决方案1】:

AppService 的默认生命周期为 25 秒,除非前台体验请求它。当服务关闭连接时,您的客户端进程将收到 ServiceClosed 事件,因此您知道下次要发送请求时需要重新打开连接。

【讨论】:

  • 感谢您的澄清,让我调查一下,我会更新帖子。
  • ServiceClosed 事件从未被触发。我更新了帖子,查看它以获取更多信息。
  • 你需要在AppServiceConnection的客户端监听ServiceClosed,而不是服务器端。
  • 非常感谢 Stefan Wick MSFT,在监听 ServiceClose 事件时,我可以恢复与服务应用程序的连接。唯一的问题是,当连接关闭时,我丢失了我发送的一个 uart 数据包。所以这让我认为服务应用程序不是管理串行通信的最佳方式。你怎么看?
  • @ElettroAle 您介意与我们分享您是如何解决此问题的吗?我也遇到了失败,但是一旦我停止客户端,如果我发送多个请求,我只能看到最后一个请求成功
猜你喜欢
  • 2019-05-22
  • 2020-09-28
  • 2018-11-03
  • 2017-05-10
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
相关资源
最近更新 更多