0

一定時間内に関数を実行するためのこのクラスがあります。

namespace Test
{
    public static class At
    {
        private static void ExecuteDelayedAction(object o)
        {
            (o as Action).Invoke();
        }

        public static void Do(Action action, TimeSpan delay, int interval = Timeout.Infinite)
        {
            new Timer(new TimerCallback(At.ExecuteDelayedAction), action, Convert.ToInt32(delay.TotalMilliseconds), interval);
        }
        public static void Do(Action action, DateTime dueTime, int interval = Timeout.Infinite)
        {
            if (dueTime >= DateTime.Now) Do(action, dueTime - DateTime.Now, interval);
        }
        public static void Do(Action action, int delay, int interval = Timeout.Infinite)
        {
            Do(action, TimeSpan.FromMilliseconds(delay), interval);
        }
    }
}

また、私のアプリケーションには と の 2 つのページがLogin.xamlありMainPage.xamlます。テスト目的で、次のコードをMainPageコンストラクターに入れました。

public MainPage()
{
    InitializeComponent();
    At.Do(delegate { Debug.WriteLine("MainPage"); }, 5000);
}

私の問題は次のとおりです。アプリケーションがMainPage最初に開くと、タイマーが正常に機能し、デリゲートが実行されます。ただし、アプリケーションがLogin最初に開いてからナビゲートするとMainPage、タイマーはサイレントに失敗します。なぜそれが起こっているのですか、どうすれば修正できますか?

4

1 に答える 1

1

あなたが作成しているタイマーはガベージコレクション(GC)されていると思われます.どこにも参照を保持しているのではなく、新しく作成されたタイマーへの参照を削除しているだけです.

ページ間を移動すると大量のメモリが作成されるため、GC がトリガーされる場合があります。

タイマー オブジェクトへの参照を保持することで修正してみてください。Do内部にプライベート タイマーを非表示にできるクラス インスタンスを作成し、それへの参照を保持します。ただし、現在の静的クラスの設計を維持したい場合は、タイマーであるオブジェクトを返すことができます。

    public static object Do(Action action, TimeSpan delay, int interval = Timeout.Infinite)
    {
        var t = new Timer(new TimerCallback(At.ExecuteDelayedAction), action, Convert.ToInt32(delay.TotalMilliseconds), interval);
        return t;
    }

次に、タイマーへの参照をページに保存する必要があります。

public MainPage()
{
    InitializeComponent();
    this.doObject = At.Do(delegate { Debug.WriteLine("MainPage"); }, 5000);
}

もちろん、MainPageが GC されている場合、タイマーも GC されますが、実行するアクションに適したものにタイマーのスコープを変更することで修正できます。

于 2012-12-30T14:39:58.487 に答える