0

特定のコレクションを取得し、アイテムをコピーし(ItemクラスにはCopy()メソッドが適切に定義されています)、アイテムにデータを入力し、入力されたコレクションをクラスのコレクションプロパティに返す、かなりプロセス集約的なメソッドがあります。

//populate Collection containing 40 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );

このメソッドは、要求に応じて、およびSystem.Timers.Timerオブジェクトの「Elapsed」イベントを介して2つの方法で呼び出されます。

現在、コレクション内の40のアイテムは、ほとんど時間がかかりません。button_clickなどによって「アドホック」に入力されるか、Timerオブジェクトによって入力されるか。

コレクション(1000個のアイテムを持つ別のMyClassオブジェクト)のサイズを大きくすると、予想どおりにプロセスに時間がかかりますが、合計で約6秒かかります。それは問題ありません。問題はありません。初期化時に呼び出されるか(form_load)、アドホックに呼び出される(button_click)と、約6秒続きます。

//populate Collection containing 1000 items
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems );

ただし、同じメソッド(コードの正確な行と同様)がSystem.Timers.Timerオブジェクトによって呼び出されています。そして、その経過には約60秒かかります(他の実行では、56秒、1分2秒、1分10秒...アイデアがわかります)。同じプロセスで10倍の長さです!

System.Timers.Timerオブジェクトがスレッドプールで実行されていることは知っています。これが理由でしょうか?スレッドプールの優先度が低くなっていますか、それともキューイング全体に時間がかかっていますか?

要するに、これへのより良いアプローチは何でしょうか?System.Windows.Forms.Timerを使用して同じUIスレッドで実行しますか?

ありがとう!

わかりました、いくつかの追加情報:

タイマー操作は、UIによって呼び出されているDLL内で発生しています。メインの「handler」クラス自体には、すべて同じイベントハンドラーにサブスクライブしているタイマーオブジェクトのコレクションがあります。ハンドラークラスの初期化は、次のように機能します。

UpdateIntervalTimer tmr = new UpdateIntervalTimer(indexPosition);
tmr.Interval = MyClass.UpdateInterval * 60000; //Time in minutes
tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed);
this.listIntervalTimers.Add(tmr);

私は実際にTimerクラスを継承して、それに'index'プロパティを与えました(eventArgsも同様です)。このようにして、1つのイベントハンドラー(tmr_Elapsed)内で、タイマーの対象となるMyClassオブジェクトを識別し、アクションを実行できます。

ハンドラークラスはすでに独自のスレッドで実行されており、カスタムイベントを発生させて、その操作に関する洞察を提供します。イベントはUI(UIコントロールのクロススレッドアクセスなど)で処理され、イベントが処理された時刻とともに表示されます。これは、「初期化」呼び出しと「アドホック」呼び出しの両方に当てはまります(これらの場合は問題ありません)。

実際の経過イベントは次のようになります。

private void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
            UpdateIntervalTimer tmr;
            tmr = (UpdateIntervalTimer)sender;

            MyClass c = listOfClasses[tmr.IndexPosition];

            observerEventArguments = new MyHandlerEventArgs("Timer is updating data for " + MyClass.ID);
            MessagePosted(this, observerEventArguments);

            try
            {
                //preparation related code


                MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems);


                observerEventArguments = new ProfileObserverEventArgs(MyClass.ID + ": Data successfully updated");
                MessagePosted(this, observerEventArguments);
            }
            catch (Exception exUpdateData)
            {
                observerEventArguments = new MyHandlerEventArgs("There was an error updating the data for '" + MyClass.ID + "': " + exUpdateData.Message);
                MessagePosted(this, observerEventArguments);
            }
        }
4

2 に答える 2

1

ええと、UIスレッドの優先度高くなる可能性があります。結局のところ、UIの応答性を維持することを目的としています。ただし、他にも発生する可能性のあることがあります。メソッドはスレッドセーフな方法でUIにアクセスしますか?もしそうなら、スレッド間でマーシャリングする必要がない場合は明らかに高速になります。

スレッドプールスレッドの優先度を上げて、パフォーマンスが向上するかどうかを確認することもできますが、それとは別に、より多くの情報が必要になります。

UIスレッドでこれを行うことお勧めしません-6秒間UIをぶら下げても、優れたユーザーエクスペリエンスにはなりません:(

于 2009-09-24T10:14:18.470 に答える
0

タイマーで作業をしている間に間隔が経過し、同じ作業が複数回行われるようになっていますか?UIタイマーはシングルスレッドであり、終了するまで再び経過することはできませんが、他のタイマーは可能であるため、UIタイマーがsystem.timers.timer/system.threading.timerよりも高速に動作すると考えることができる唯一の理由です。

于 2009-12-15T23:00:39.470 に答える