0

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

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

Win32 桌面桥应用程序激活得很好,它能够使用 HTTP 连接到 Web 服务器。但是一旦它尝试打开 WebSocket 连接,BackgroundTaskInstanceUWP 主机上的 就会收到一个取消请求,BackgroundTaskCancellationReason.SystemPolicy原因是,桌面桥应用程序将关闭。不幸的是,文档BackgroundTaskCancellationReason.SystemPolicy并没有解释取消请求的真实原因。

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

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

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

我还使用了该CheckNetIsolation工具,为 Edge 浏览器和包添加了环回豁免,但没有任何效果。HTTP 在没有环回豁免的情况下工作正常。

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

4

1 回答 1

2

好的,我解决了这个问题。多亏了我偶然发现的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();
        }
    }
}
于 2017-10-26T22:57:49.903 回答