WinRT中的后台任务回调(Cordova Windows插件)

WinRT中的后台任务回调(Cordova Windows插件),cordova,windows-phone,cordova-plugins,visual-studio-cordova,background-task,Cordova,Windows Phone,Cordova Plugins,Visual Studio Cordova,Background Task,我正在为Cordova制作插件,目前我正在努力使其支持Windows平台。我有一个用C#编写的DLL,我想在我的插件中使用其中的功能。为了做到这一点,我制作了Windows运行时组件项目,它是围绕C#DLL的“包装器”,从那里我将方法公开给Cordova中的Java脚本,并且我可以成功地调用它们。那么,我们之间的沟通, App <-> Plugin <-> WinRT <-> C# DLL 一旦代码执行到这一部分,我就断定应用程序只是默默地跳过这一部分,Pr

我正在为Cordova制作插件,目前我正在努力使其支持Windows平台。我有一个用C#编写的DLL,我想在我的插件中使用其中的功能。为了做到这一点,我制作了Windows运行时组件项目,它是围绕C#DLL的“包装器”,从那里我将方法公开给Cordova中的Java脚本,并且我可以成功地调用它们。那么,我们之间的沟通,

App <-> Plugin <-> WinRT <-> C# DLL
一旦代码执行到这一部分,我就断定应用程序只是默默地跳过这一部分,ProcessQueue()方法永远不会在后台任务中开始执行。首先,我认为问题可能在于我在C#中启动此任务的方式,所以我尝试了几种替代方法来启动新的后台任务-运气不好

然后我想我可能会从后台线程调用Java脚本中的插件(从这个假设中可以看出,我不是Cordova/Java脚本专家),但很快意识到这不会发生。我发现作为Cordova插件的一部分对本机代码的调用不是在主UI线程中执行,而是在其他线程中执行,但似乎仍然无法从该线程中的C#DLL创建后台任务

然后我阅读了WinRT组件中的后台任务,并尝试实现它。我将此项目用作参考:

在该项目中,他们从C#app触发后台任务。我不知道如何从Cordova应用程序中执行它(甚至可以从那里执行吗?),所以我尝试在Java脚本代理调用WinRT组件中的一个方法时触发它。所以基本上,我的后台任务类存在于WinRT组件中(如示例中),但我是从WinRT而不是从应用程序触发它。当然,还有一个区别是,我使用Cordova应用程序的package.windows10.appxmanifest来注册后台任务

在我这样做之后,我并没有得到编译错误,触发任务的代码工作并得到执行,但后台任务的Run方法从未被调用

所以,我的问题是:有人知道我如何完成这件事吗?通常如何在WinRT组件或Windows Cordova插件中启动后台任务

非常感谢您的回答

干杯


更新#1

好的,我设法解决了我最初的问题,下面是代码

我用Dummy.cs类创建了WinRT组件,Dummy.cs类是WinJS代码的入口点,它获取我的一些自定义对象作为参数。类看起来像这样:

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Runtime.Serialization;
using Windows.Foundation.Collections;
using Windows.ApplicationModel.Background;

namespace DummyWinRT
{
    public sealed class WRTDummy
    {
        private static ApplicationTrigger _trigger;

        public async static void MethodCalledFromWinJS(MyCustomObject myObject)
        {
            await BackgroundExecutionManager.RequestAccessAsync();

            foreach (var t in BackgroundTaskRegistration.AllTasks)
            {
                t.Value.Unregister(true);
            }

            _trigger = new ApplicationTrigger();

            BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
            builder.TaskEntryPoint = "DummyWinRT.BackgroundTaskTest";
            builder.Name = "AppTrigger";
            builder.SetTrigger(_trigger);
            var registration = builder.Register();

            var arguments = new ValueSet();

            try {
                arguments.Add("key1", "value1");
                arguments.Add("key2", "value2");
                arguments.Add("key3", nowWhat);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
            }

            await _trigger.RequestAsync(arguments);
        }
    }
}
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Foundation.Collections;
using Windows.ApplicationModel.Background;
using System.Runtime.InteropServices.WindowsRuntime;

namespace DummyWinRT
{
    public sealed class BackgroundTaskTest : IBackgroundTask
    {
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();

            // If you want to get passed arguments.
            var details = taskInstance.TriggerDetails as ApplicationTriggerDetails;
            var args = details.Arguments as ValueSet;
            var value1 = args["key1"].ToString();
            var value2 = args["key2"].ToString();

            // Do what ever you want.

            _deferral.Complete();
        }
    }
}
我的背景任务如下所示:

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Runtime.Serialization;
using Windows.Foundation.Collections;
using Windows.ApplicationModel.Background;

namespace DummyWinRT
{
    public sealed class WRTDummy
    {
        private static ApplicationTrigger _trigger;

        public async static void MethodCalledFromWinJS(MyCustomObject myObject)
        {
            await BackgroundExecutionManager.RequestAccessAsync();

            foreach (var t in BackgroundTaskRegistration.AllTasks)
            {
                t.Value.Unregister(true);
            }

            _trigger = new ApplicationTrigger();

            BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
            builder.TaskEntryPoint = "DummyWinRT.BackgroundTaskTest";
            builder.Name = "AppTrigger";
            builder.SetTrigger(_trigger);
            var registration = builder.Register();

            var arguments = new ValueSet();

            try {
                arguments.Add("key1", "value1");
                arguments.Add("key2", "value2");
                arguments.Add("key3", nowWhat);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
            }

            await _trigger.RequestAsync(arguments);
        }
    }
}
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Foundation.Collections;
using Windows.ApplicationModel.Background;
using System.Runtime.InteropServices.WindowsRuntime;

namespace DummyWinRT
{
    public sealed class BackgroundTaskTest : IBackgroundTask
    {
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();

            // If you want to get passed arguments.
            var details = taskInstance.TriggerDetails as ApplicationTriggerDetails;
            var args = details.Arguments as ValueSet;
            var value1 = args["key1"].ToString();
            var value2 = args["key2"].ToString();

            // Do what ever you want.

            _deferral.Complete();
        }
    }
}
我遇到的新问题如下。当我“打包”参数以发送到后台任务时,您可能已经注意到这一行:

arguments.Add("key3", nowWhat);
在我的例子中,
now应该是
delegate
。所以,无论是在WinJS中还是在WinRT中,我都想声明一个方法,一旦其中的某些逻辑被执行(异步的事情),我想将该方法传递给后台任务来执行它

传递给后台任务的参数必须是可序列化的

您知道我如何将
委托
操作
Func
从WinRT传递到后台任务,以便我可以将后台任务中的一些内容报告回WinRT吗?或者,如果有任何其他方法可以实现这一点,我将有兴趣听取建议?


提前谢谢。

您最终解决了吗?此外,我可以为C++DLL做同样的包装吗?不完全可以,我确实找到了一些(针对我的需求)可能性非常有限的解决方案,但我没有找到时间写下这件事。一旦我回到这个任务中,我最终会把它写下来。