我正在为Cordova制作插件,目前我正在尝试使其支持Windows平台。我有一个用C#编写的DLL,我想在我的插件中使用那里的功能。为了做到这一点,我制作了Windows运行时组件项目,这是"包装器"围绕C#DLL,从那里我将方法暴露给Cordova中的Java Script,我可以成功调用它们。那么,
之间的沟通App <-> Plugin <-> WinRT <-> C# DLL
工作正常。
在某些时候(在C#DLL中的一个方法中)我正在尝试执行以下操作:
Task.Factory.StartNew(() => ProcessQueue(), TaskCreationOptions.LongRunning);
一旦代码执行到达这一部分,我得出结论,app只是默默地跳过这部分,ProcessQueue()方法永远不会开始在后台任务中执行。首先我认为问题可能与我在C#中启动此任务的方式有关,所以我尝试了几个替换来开始新的后台任务 - 没有运气。
然后我想我可以从后台线程调用Java Script中的插件(我不是Cordova / Java Script专家,你可以从这个假设中看到),但很快意识到它不会发生。我发现作为Cordova插件的一部分对本机代码进行的调用不是在主UI线程中执行,而是在其他一些线程中执行,但仍然无法在该线程中从C#DLL创建后台任务。
然后我阅读了WinRT组件中的后台任务并试图实现它。我使用此项目作为参考:https://github.com/Microsoft/Windows-universal-samples/tree/93bdfb92b3da76f2e49c959807fc5643bf0940c9/Samples/BackgroundTask/cs/BackgroundTask
在该项目中,他们正在从C#app触发后台任务。我不知道如何从Cordova应用程序中执行此操作(甚至可以从那里执行此操作吗?),因此当从Java Script代理调用WinRT组件中的一个方法时,我尝试触发它。所以基本上,我的后台任务类存在于WinRT组件中(如示例中所示),但我是从WinRT而不是从应用程序触发它。当然,另一个区别是我使用Cordova应用程序的package.windows10.appxmanifest来注册后台任务。
执行此操作后,我没有编译错误,触发任务的代码工作并执行,但后台任务的Run方法永远不会被调用。
所以,我的问题是:有谁知道我怎么能完成这件事?如何在WinRT组件或Windows Cordova插件中启动后台任务?
非常感谢任何答案。
干杯
更新#1
好的,我设法解决了我的原始问题,这是代码。
我用Dummy.cs类创建了WinRT组件,这是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();
}
}
}
我遇到的新问题如下。当我&#34;包装&#34;发送到后台任务的参数,你可能已经注意到这一行:
arguments.Add("key3", nowWhat);
就我而言,nowWhat
应该是delegate
。因此,无论是在WinJS还是在WinRT中,我都想声明我想要传递给后台任务的方法,以便在执行某些逻辑后执行它(异步事物)。
传递给后台任务的参数需要为serializable
。
您是否知道如何将delegate
或Action
或Func
从WinRT传递到后台任务,以便我可以将后台任务中的一些内容报告给WinRT ?或者,如果有其他方法可以实现这一点,我会有兴趣听取建议吗?
提前谢谢。