8

我在另一个我无法解决 的问题之后发布了这个特定问题。

简而言之:即使我创建了一个静态类(带有静态变量和/或属性),主应用程序和后台代理也不使用相同的静态类,而是都创建了它的新实例;所以不可能在这些项目之间共享数据!!

要测试它:

  • 创建一个新的 Windows Phone 应用程序(称为AppTest
  • 添加一个 ScheduledTask 项目(称为Agent
  • AppTest中引用项目代理
  • 创建一个新的 Windows Phone 库项目(称为Shared
  • AppTestAgent中都引用了项目Shared

然后使用这个基本的测试代码。

应用测试

private readonly string taskName = "mytest";
PeriodicTask periodicTask = null;

public MainPage()
{
    InitializeComponent();

    Vars.Apps.Add("pluto");
    Vars.Order = 5;

    StartAgent();
}

private void RemoveTask()
{
    try
    {
        ScheduledActionService.Remove(taskName);
    }
    catch (Exception)
    {
    }
}
private void StartAgent()
{
    periodicTask = ScheduledActionService.Find(taskName) as PeriodicTask;
    if (periodicTask != null)
        RemoveTask();
    periodicTask = new PeriodicTask(taskName)
    {
        Description = "test",
        ExpirationTime = DateTime.Now.AddDays(14)
    };

    try
    {
        ScheduledActionService.Add(periodicTask);
        ScheduledActionService.LaunchForTest(taskName, 
                TimeSpan.FromSeconds(10));
    }
    catch (InvalidOperationException exception)
    {
    }
    catch (SchedulerServiceException)
    {
    }
}

代理人

protected override void OnInvoke(ScheduledTask task)
{
    if (Vars.Apps.Count > 0) 
        Vars.Order = 1;

    NotifyComplete();
}

共享

public static class Vars
{
    public static List<string> Apps = null;
    public static int Order;

    static Vars()
    {
        Apps = new List<string>();
        Order = -1;
    }
}

当您调试主应用程序时,您可以看到调用了静态类的静态构造函数(这是正确的),但是调用代理时Vars没有“使用”,而是再次调用构造函数,因此创建了一个不同的实例。
为什么?如何在主应用程序和后台代理之间共享数据?
我已经尝试将Vars类放在代理类和命名空间中,但行为是相同的。

4

4 回答 4

8

最简单的事情是使用独立存储。例如,从主应用程序:

using (Mutex mutex = new Mutex(true, "MyData"))
{
    mutex.WaitOne();
    try
    {
        IsolatedStorageSettings.ApplicationSettings["order"] = 5;
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}
//...

在代理中:

using (Mutex mutex = new Mutex(true, "MyData"))
{
    mutex.WaitOne();
    try
    {
        order = (int)IsolatedStorageSettings.ApplicationSettings["order"];
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}

// do something with "order" here...

您需要使用进程级同步和互斥锁来防止数据损坏,因为代理和应用程序是两个独立的进程,并且可能同时使用隔离存储执行某些操作。

于 2012-07-10T18:35:12.410 回答
5

静态变量的值是每个加载的App Domain的“实例化” ,这是您正在运行的进程的“子集”。因此,每个 AppDomain 的静态变量具有不同的值,因此每个正在运行的进程也具有不同的值。

如果您必须在进程之间共享数据,则需要将其存储在某个地方(例如数据库),或者您需要在进程之间设置一些通信(例如 MSMQ 或 WCF)。

希望这可以帮助。

于 2012-07-09T06:40:00.827 回答
3

找了好久,终于找到一篇文章说:

由于我们的 EventTiles 应用程序和它的 PeriodicTask 在不同的进程中运行,它们彼此完全分离,这意味着它们拥有自己想要访问的变量的副本,即使这些变量是在单独的项目中定义的。

因此,使用“简单”静态变量/属性在主应用程序和周期性任务之间共享数据是不可能的;我们必须读/写数据库或隔离存储或任何我们喜欢的东西。

我觉得这很疯狂,但这就是故事。

于 2012-07-09T07:46:02.630 回答
2

MS 建议如下:

前台应用程序和后台代理之间的通信

在前台应用程序和后台代理程序之间传递信息可能具有挑战性,因为无法预测代理程序和应用程序是否会同时运行。以下是为此推荐的模式。

1.对于定期和资源密集型代理:使用 LINQ 2 SQL 或隔离存储中的文件,该存储由互斥锁保护。对于前台应用程序写入而代理仅读取的单向通信,我们建议使用带有 Mutex 的隔离存储文件。我们建议您不要使用 IsolatedStorageSettings 在进程之间进行通信,因为数据可能会损坏。

2.对于音频代理:将自定义数据存储在 AudioTrack 类的 Tag 属性中。对于从音频代理到前台应用程序的通知,请阅读 PlayStateChanged 事件处理程序中的 Tag 属性。要将数据从前台应用程序传递到音频代理,请在 OnPlayStateChanged(BackgroundAudioPlayer, AudioTrack, PlayState) 方法的实现中读取当前轨道的 Tag 属性。

见这里: http: //msdn.microsoft.com/en-us/library/hh202944 (v=vs.92).aspx

于 2012-08-26T10:56:54.270 回答