2

OnCreate()毎秒1回実行する関数があります。OnCreate現在の時刻 (現在の秒) に基づいて他の関数を呼び出します。しかし、各関数を 内に個別に記述する必要はなく、関数OnCreateをグループ化できるようにしたいと考えています。つまり、10 秒の時点で、新しい X を作成する関数 's をOnCreate呼び出したいと考えています。CreateFiveX新しい秒ごとに 5 秒間。OnCreate次に、20 秒のマークで、同じ関数を再度呼び出したいと思います。

イベントとデリゲートを使用してこの問題を解決したいと思います。の開始時にOnCreate、現在の時間を取得してすべてのサブスクライバーに送信するイベントを発生させたいと考えています.リスト。

問題は、あまりにも時間が経っても、これを行う方法を理解できないことです。さらに困難にするために、OnCreate呼び出す関数に追加のパラメーターを渡したいと考えています。どんな助けでもいいです、ありがとう。

4

5 に答える 5

3

おそらく、あなたはリアクティブホイールを再発明しようとしていますか?

Reactive Extensions がインストールされ、参照されていること、およびこれらの名前空間がスコープ内にあることを確認してください。

System.Reactive
System.Reactive.Linq

次に、(例として) 次のコンビネータを結合して使用できます。

  • Observable.Interval(timespan)イベントを作成するtimespan
  • Observable.Take(number)それら(または他のイベント)を特定のものに制限するnumber
  • Observable.Timer()現在または将来/過去の時間から、特定の時間または時間オフセットで単一のイベントを作成する
  • Observable.Do(action)Observable.Subscribe(action)ストリームに基づいて副作用やその他の種類のアクションを実行する
  • Observable.Repeat(number)上記のいずれかを何度も繰り返す
  • Observable.Generate()状態から観測可能なシーケンスを生成する

そして、列挙型イベントパターンなどからオブザーバブルを作成するものなど、他の多くの.

具体的な例があれば、Rx を使用してそれを実行する方法を示すことができます。StackOverflow の関連セクションを参照することもできます。

于 2012-05-11T02:18:15.623 に答える
1

イベントを使用したコードのサンプル、およびパラメーター化されたハンドラー:

public class TheTimer
{
    // define delegate with desired parameters
    public delegate void TimerDelegate(int param1, string param2);

    // expose the event
    public event TimerDelegate OnTimer;

    // This is the handler of a regular Timer tick:or your OnCreate() function
    Timer1_Tick()
    {
        if (OnTimer != null) // if susbcribed handlers
        {
            OnTimer(1, "value"); // raise your cutom event, passing the params
        }
    }
}

// Implement classes with functions that can handle the event
public class HandlerFunctions
{
    public void HandleTimer(int p, string p2)
    {
       // do whatever   
    }
}

// Use your classes
public class TimerUserClass
{
    public static void UseTimers()
    {
        // Create objects
        TheTimer theTimer = new TheTimer();
        HandlerFunctions handler1 = new HandlerFunctions();
        HandlerFunctions handler2 = new HandlerFunctions();
        // SUbscribe events
        theTimer.OnTimer += handler1.HandleTimer;
        theTimer.OnTimer += handler2.HandleTimer;
        // un-susbcribe
        theTimer.OnTimer -= handler1.HandleTimer;
    }
}
于 2012-05-11T00:28:22.127 に答える
1

ロジックがどれほど複雑になるかによっては、代わりにステート マシンの実装を検討することをお勧めします。私自身のステート マシンは一時的なイベントを実装しているので、たとえば次のように言えます。

 machine.Every(new TimeSpan(hours: 0, minutes:0, seconds:5), eScheduledCheck);

または、メソッドを使用して 5 つのイベントを連続してスケジュールすることもできます.At

1 秒ごとにメソッドを呼び出すだけでTick()、ステート マシンが必要に応じて前進します。さらに良いことに、次にアクションが必要であることを示したときに、スリープするか、タイマーを設定することもできます。

スケジュールされたイベントをキャンセルしたり、新しいイベントをスケジュールしたり、単に通常のステート マシンのように動作したりするために他のトリガーをプログラムする必要がある場合は、それも実行できます。また、階層状態もサポートしています。

状態を保存して再開し、スケジュールされたすべてのイベントを通常どおり実行できるようにする必要がある場合は、そのシナリオ (再起動後も存続する必要がある NT サービスなど) にも対応するように設計されています。

Nugetからソース コードを取得できます。

于 2012-05-11T00:50:10.513 に答える
1

これは興味深い質問だと思いました.1秒ごとに実行される関数についての説明はよくわかりませんが、5秒間実行される別の関数を呼び出します.欠けている部分はカプセル化する方法ですメソッド呼び出し。そこで、あらかじめ決められたタイマー刻みで呼び出されるタイマーとActionデリゲートを使用するこのサンプルを作成しました。探しているものであれば、これを設計に推定できるはずです。

class TimedFunction
{
    public Action<TimedFunction, object> Method;
    public int Seconds = 0;

    public TimedFunction() {
    }

}

class Program
{

    static int _secondsElapsed = 0;
    static List<TimedFunction> _funcs = new List<TimedFunction>();
    static int _highestElapsed = 0;
    static Timer _timer;

    static void Main(string[] args) {

        var method = new Action<TimedFunction, object>((tf, arg) => Console.WriteLine("{0}: {1}", tf.Seconds, arg));

        _funcs.Add(new TimedFunction() { Seconds = 5, Method = method });
        _funcs.Add(new TimedFunction() { Seconds = 8, Method = method });
        _funcs.Add(new TimedFunction() { Seconds = 13, Method = method });
        _funcs.Add(new TimedFunction() { Seconds = 10, Method = method });

        _highestElapsed = _funcs.Max(tf => tf.Seconds);

        _timer = new Timer(1000);
        _timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
        _timer.Start();

        Console.WriteLine();
        Console.WriteLine("----------------------");
        Console.WriteLine("Hit any key to exit");
        Console.ReadKey(true);
    }

    static void t_Elapsed(object sender, ElapsedEventArgs e) {
        _secondsElapsed++;
        foreach (TimedFunction tf in _funcs) {
            if (tf.Seconds == _secondsElapsed) {
                tf.Method(tf, DateTime.Now.Ticks);
            }
        }

        if (_secondsElapsed > _highestElapsed) {
            Console.WriteLine("Finished at {0} seconds", _secondsElapsed - 1);
            _timer.Stop();
        }
    }
}

これは出力です:

----------------------
Hit any key to exit
5: 634722692898378113
8: 634722692928801155
10: 634722692949083183
13: 634722692979496224
Finished at 13 seconds

(これは、コンソールがキープレスを待っている間、タイマーがまだ実行されているため機能します)

Actionすべてのオブジェクトに同じデリゲート インスタンスを使用しましたが、TimedFunction別のオブジェクトを使用することを妨げるものは何もないことに注意してください。デリゲートが受け取る引数の型を定義する必要はありますが、いつでもobjectまたは他の型を使用して、必要なものを渡すことができます。

また、エラー チェックはなく、これを実行しているアプリケーションの種類についても言及していません。たとえば、おそらく別のスレッドを使用したいと思うでしょう。ああ、タイマーの解像度はそれほど良くないので注意してください。

お役に立てれば。

于 2012-05-11T00:55:52.427 に答える