0

私は、ユーザーがイベントを発生させるために1つ(または複数)のタイマーを作成できるようにする必要があるプロジェクトに取り組んでいます。ユーザーは、タイマーをアクティブにする必要があるかどうか、タイマーが起動する頻度などの変数を、タイマーが起動しているときに発生する他の変数とともに定義する必要があります。

これらの変数はすべて辞書(Disctionary)に格納され、オブジェクトはユーザーが設定したすべての変数を保持し、文字列はユーザ​​ーがこのタイマーに選択した名前です。

次に、プログラムでこのディクショナリをループして、変数t_Activeがtrueに設定されているすべてのオブジェクトを検索します(これはすでに達成しています)。私が理解するのに助けが必要なのは次のとおりです。変数が検出され、それがtrueに設定されている場合は、このために作成されたタイマーがすでにあるかどうかを確認するプログラムが必要です。そうでない場合は、作成してタイマーに関連するパラメーターを設定する必要があります。2つの変数t_numとt_periodは、タイマーの間隔を決定する必要があります。t_numはintであり、t_periodは、分、時間、または日のいずれかに設定される文字列です。

t_numを60000(分)、3600000(時間)、または86400000と組み合わせると、正しい間隔が得られます。

しかし、ユーザー定義のアクティブオブジェクトごとにプログラムでタイマーを作成するにはどうすればよいでしょうか。そして、タイマーがすでに作成されているかどうかをプログラムに検出させるにはどうすればよいですか?

私はこことグーグルの両方で検索してきましたが、今のところ私にとって意味のあるものに出くわしていません。私はまだC#を学んでいるので、皆さんにとって意味のあることは、必ずしも私にとって意味がないかもしれません。:)

私が必要としていることを十分に説明できたと思います。私がわからない場合は、明確にするように依頼してください。

編集:

また、前述の辞書もXMLファイルに保存されるため、ユーザーはいつでもすべての設定を取得できます。

編集2:

@hatchetこれがうまくいくかどうか疑問に思っています。私はそれを機能させようとしましたが、いくつかの困難にぶつかっています(私は経験がなく、あなたの擬似コードを完全に理解していないためです。エラーが発生し、いくつかは解決でき、いくつかはできませんでした't。(完全に機能するコードは期待していませんでした。心配しないでください))。

また、ユーザーはタイマーを変更できる必要があります。メインフォームには、いくつかのテキストボックスと3つのボタンがあります。フォームはメッセージの送信に使用されます。ユーザーは、メッセージを手動で送信するか、メッセージをタイマーに追加するか、タイマーを編集するかを選択できます。

ユーザーが手動ボタンを押すと、メッセージはすべての受信者に1回送信されます。メッセージをタイマーに追加すると、新しいサブフォームがポップアップ表示され、次の詳細を設定できます。文字列名前(タイマーの)DateTime Start_date CheckBox Ending DateTime End_date NumericUpDown Seconds(minimum value of 15 minutes)Combobox Minutes、Hours 、アクティブな日数チェックボックス

ユーザーがメッセージをタイマーに追加すると、TimerSettingsはsting、Object(すべての詳細をまとめたカスタムオブジェクト)として辞書に追加されます。

メインフォームの変更ボタンを押すと、サブフォームを開く前に、プログラムは対応するタイマーを探し(メインフォームにはすべてのタイマーが追加されたコンボボックスがあります)、タイマーを停止してからサブフォームを開いてユーザーが詳細を編集します。

サブフォームには削除ボタンもあり、ユーザーはタイマーを削除できます。

タイマーを追加または変更するとき、mainformはタイマーをキャッチし、変更をXMLファイルとコンボボックスに書き込みます。そして、このメッセージのタイマーがすでに存在するかどうかを確認し、存在しない場合はタイマーを再起動する必要があります。

ただし、このためにソリューションをどのように機能させるべきかわかりません。メッセージの送信手順は、受信者の数に応じて30秒から5分かかります(42を超えることはできません(プログラムは、42を超える受信者を許可しない別のプログラムへのインターフェイスです))。

いくつかのタイマーが問題になる可能性があることは理解していますが、いずれにせよ、ユーザーが最大10個を超えるタイマーを必要とすることはないと思います。そのため、たとえば15個のタイマーの制限が組み込まれている可能性があります。

4

2 に答える 2

1

そのアプローチでタイマーがどれだけうまくスケーリングするかはわかりません。これらのイベントを管理するための他のアプローチを調査する価値があるかもしれません。@hatchetがコメントしたばかりなので、次のイベントに1つのタイマーを設定できます。そのアプローチを使用すると、実行時に次のイベントを設定できます。

もう1つの可能性は、データベースと、すべてのアクションを期限付きのタイムスタンプで実行する<小さな期間>ごとに実行されるタイマーを使用することです。

于 2012-07-05T02:13:09.263 に答える
1

これは、アイデアを伝えるための一種の擬似コードC#です。私はこれと同じことをしましたが、そのコードを貼り付けると混乱するほど、異なる詳細が十分にあります。ですから、私の頭から離れて、このセミコードは、あなたの質問に対する私のコメントが何を意味するのかを示すために、実際のコードに十分に近いことを願っています。

このようなクラスがあるとしましょう

public delegate void Work();

public class TimedThing {
    public int IntervalSecs;
    public DateTime NextFiring;
    public event Work OnWork;        
}

次に、コントローラークラスがあります

public class TimedGroup {
    TimedThing[] things;
    System.Timers.Timer timer;

    public TimedGroup() {
        this.timer = new System.Timers.Timer();
        this.timer.AutoReset = false;
        this.timer.Elapsed += TimerFired;
    }
            ...
    // some methods for adding and removing TimerThings
            ...
    public void Start() {
        this.timer.Interval = 1; // just to get things started
        this.timer.Enabled = true;
    }
    public void Stop() {
        this.timer.Enabled = false;
    }
    private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) {
        DateTime now = DateTime.Now;
        // let's have timer fire at least as frequently as every 5 minutes
        // if we need to have it fire sooner than that, it will get set below
        DateTime next = now.AddMinutes(5); 
        foreach(var thing in this.things) {
            if (thing.nextFiring <= now) {
                var task = Task.Factory.StartNew(() => DoWork(thing));
                thing.NextFiring = thing.NextFiring.AddSeconds(thing.IntervalSeconds);
                // or maybe this is more appropriate
                // thing.NextFiring = Now.AddSeconds(thing.IntervalSecs);
            }
            if (thing.NextFiring < next) next = thing.NextFiring;
        }
        // set the timer to fire whenever the next soonest work needs to be done
        this.Timer.Interval = (next - now).TotalMilliseconds;
        this.Timer.Enabled = true;
    }
    private void DoWork(TimedThing thing) {
        thing.Work();
    }
}

対処しなければならない詳細がある可能性がありますが、これらの詳細の多くは、すべてにタイマーを使用しているか、すべてに単一のタイマーを使用しているかに関係なく対処する必要があります。たとえば、あるものの作業に通常10秒かかるが、場合によっては60秒かかることがあり、時間間隔が45秒に設定されている場合はどうでしょうか。前の発砲で開始された前の作業はまだ実行中ですが、次の発砲でその作業を再度実行したい場合があります。これらがどのような作業を行っているかによって、それが望ましい場合と望ましくない場合があります。望ましくない場合は、生成されるタスクの監視を追加して、前の作業がまだ完了していないために作業をスキップする必要があるかどうかを確認する必要があります。もう1つは、優雅なワインディングをコーディングすることです。タイマーをセットするとき。Enabledがfalseに設定されているのに、System.Timer.Timerがイベントを発生させるのはなぜですか?)。それはいくつかの奇妙な振る舞い/バグを引き起こす可能性があります。

于 2012-07-05T06:09:21.263 に答える