【问题标题】:Edge extension: BackgroundTaskInstance cancels with SystemPolicy reason when DesktopBridge app tries to open WebSocket边缘扩展:当 DesktopBridge 应用程序尝试打开 WebSocket 时,BackgroundTaskInstance 因 SystemPolicy 原因取消
【发布时间】:2017-10-24 18:59:53
【问题描述】:

我创建了一个 Edge 浏览器扩展,它使用原生消息传递到通过桌面桥技术运行的原生应用程序。我使用 SecureInput 作为示例,其中包含 Edge 扩展、UWP 主机和 Win32 桌面桥应用程序。

我需要 Win32 桌面桥应用程序来使用 HTTP 和 WebSocket 连接到 Web 服务,因此我在包清单中添加了一个 internetClientServer 和一个 privateNetworkClientServer 功能,除了已经存在的 runFullTrust 一个。

Win32 桌面桥应用程序可以正常激活,并且能够使用 HTTP 连接到 Web 服务器。但是,一旦它尝试打开 WebSocket 连接,UWP 主机上的BackgroundTaskInstance 就会收到以BackgroundTaskCancellationReason.SystemPolicy 为理由的取消请求,并且桌面桥应用程序将关闭。不幸的是,BackgroundTaskCancellationReason.SystemPolicy 的文档并没有详细解释取消请求的真实原因。

我尝试使用两个 WebSocket 类:System.Net.WebSockets.ClientWebSocketWindows.Networking.Sockets.MessageWebSocket,结果相同。没有花哨的代码,只是普通的

var socket = new MessageWebSocket();
...
await socket.ConnectAsync(new Uri("wss://127.0.0.1:9001/myservice"));

其他 WS 客户端可以使用相同的 WebSocket 服务端点,所以我想这里没有服务器/防火墙/防病毒问题。

我还玩过CheckNetIsolation 工具,为 Edge 浏览器和包添加了环回豁免,但没有任何效果。没有环回豁免,HTTP 工作正常。

任务取消的真正原因可能是什么,有什么可能的方法来防止它?

【问题讨论】:

  • 这是 Edge Extension 特有的,还是在常规后台任务中也会失败?您还可以澄清一下:您是从 Win32 组件还是后台任务组件进行 WebSocket 调用?
  • Stefan,我没有在 Edge 之外尝试过。 WebSocket 调用是从 Win32 应用程序发出的,但问题实际上与 WebSocket 无关,请参阅我的回答。
  • 有道理。我以前看过这个:-)

标签: websocket uwp desktop-bridge microsoft-edge-extension


【解决方案1】:

好的,我解决了这个问题。感谢this comment by Tom Shane 我偶然发现,我意识到BackgroundTaskCancellationReason.SystemPolicy 告诉系统关闭后台任务以释放一些系统资源,而在我的情况下它发生是因为我没有获得在我的异步事件处理程序中延迟。当事件处理程序在没有延迟的情况下屈服时,系统决定它可以关闭任务。以下是代码的摘要版本:

static class Program
{
    static AppServiceConnection connection = null;

    [STAThread]
    static void Main(string[] args)
    {
        Thread appServiceThread = new Thread(new ThreadStart(ThreadProc));
        appServiceThread.Start();
        Application.Run();
    }

    static async void ThreadProc()
    {
        try {
            connection = new AppServiceConnection();
            connection.AppServiceName = "...";
            connection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
            connection.RequestReceived += OnRequestReceived;
            connection.ServiceClosed += OnServiceClosed;
            var status = await connection.OpenAsync();
            ....
        }
        catch (Exception e) { ... }
    }

    private static async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var defer = args.GetDeferral();   // <== that was missing, rookie mistake!
        try {
            var msg = ParseMessage(args.Request.Message);
            if (msg.type.Equals("ws")) {
                // this method was truly async
                // and every time it yielded the issue was revealed
                await HandleWsMessage(request, msg); 
            }
            else if (msg.type.Equals("http")) {
                // but this method was actually synchronous despite being marked as "async" 
                // and it never yielded, masking the issue for HTTP client
                await HandleHttpMessage(request, msg);
            } 
        }
        catch (Exception e) { ... }
        finally {
            defer.Complete();
        }
    }
}

【讨论】:

    猜你喜欢
    • 2011-12-17
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2014-03-20
    • 2020-10-26
    • 2016-12-11
    相关资源
    最近更新 更多