WinRT、Javascript和随机的“访问被拒绝”异常

5

一些背景信息

最近我正在开发一些 Windows 8 HTML5/WinJS 应用程序。这个应用程序使用 WinRT 组件完成一些工作。

JavaScript 部分与整个 WinRT 组件协同开始异步操作:回调函数由 JavaScript 给出,当 WinRT 有一些异步结果时,会调用它。

我忘了提到,整个 Windows 8 应用程序并不使用“单页方法”(single page approach)。

问题

如果整个异步操作在某个页面中被调用,并且您不浏览到其他页面,那么一切都如预期所示。

但是,当您浏览到其他页面时会发生什么? 当 WinRT 组件需要通知 JavaScript 部分关于异步操作的结果时:ACCESS DENIED EXCEPTION!您的应用程序崩溃了。

我到目前为止尝试过的方法

  • 整个 WinRT 组件方法返回一个 IAsyncOperation<T>:在导航到其他页面之前,在 JavaScript 中调用 .cancel() 方法 => 没有成功
  • 我将回调函数放入 WinJS.Application.sessionState 中,以确保整个函数不会被垃圾回收器销毁 => 没有成功

问题是...

我有任何机会通知 WinRT 组件取消它的异步操作并不尝试将控件返回到 JavaScript 回调吗?

提前感谢

您可以检查其他人以前遇到了相同的问题:


@markp3rry 这是一个技术演示,只有一个页面。但我需要打开一些外部网页,我在另一个应用程序页面中使用了 iframe 和返回按钮到主菜单。我认为创建真正的导航所需的努力不值得在这个小项目中使用... - Matías Fidemraizer
抱歉...那是一个有点愚蠢的评论(我已经删除了,但你比我更快)。 - markp3rry
1个回答

2

在一些试错之后,我找到了解决方案。

回答自己的问题:

我有机会通知WinRT组件取消其异步操作,并不尝试将控制返回给JavaScript回调吗?

是的,但不能直接

那么,如何实现呢?

  1. 在WinRT的C#组件端,在调用异步操作之前设计一个CancellationTokenSource属性,并将其分配。
  2. 创建一个CancellationTokenSource实例,并在调用异步操作之前将其设置为先前步骤中创建的属性。
  3. 在将.NET任务转换为WinRT IAsyncOperation<T>之前,在异步操作中流畅地使用ContinueWith方法,并将作为先前实例化的CancellationTokenSource的一部分创建的CancellationToken提供给ContinueWith方法(请参阅取消任务:http://msdn.microsoft.com/en-us/library/dd997396.aspx)。
  4. 在WinRT组件中实现一个CancelCurrentAsyncOperation方法,该方法将调用CancellationTokenSource.Cancel()
  5. 在导航到另一页之前,在WinJS / JavaScript中调用先前的CancelCurrentAsyncOperation方法。

WinRT组件示例代码:

public sealed class MyWinRTComponent 
{
   private CancellationTokenSource { get; set; }

   public void CancelLastAsyncOperation() 
   {
       if(CancellationTokenSource != null) 
       {
           CancellationTokenSource.Cancel();
       }
   }

   public IAsyncOperation<string> DoSomethingAsync() 
   {
        CancellationTokenSource = new CancellationTokenSource();

        return DoSomethingAsync()
                     .ContinueWith<string>(task => task.Result, CancellationTokenSource);
   }
}

JavaScript示例代码:

var component = new MyWinRTComponent();
component.doSomethingAsync().then(function(text) {
   // Do stuff
});

// Before navigating to other page
component.cancelCurrentAsyncOperation();

那对我有用!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接