4

処理する必要がある一連の計算があります。計算とその実行順序はすべて、ユーザーが UI で定義します。

次々と走っていくだけなら、さほど難しくはないだろう。ただし、一部の計算は同時に処理する必要があり、すべての計算はいつでも個別に一時停止できる必要があります。また、いつでも注文を再配置したり、処理する新しい計算を追加したりできる必要があります。だから私が何をするにしても、これを処理するのに十分柔軟でなければなりません.

UI で、ユーザー コントロールのリストボックス (必要に応じてキュー) を想像してください。各ユーザー コントロールには計算の名前と一時停止ボタンが表示されます。また、処理中にいつでもこのリストに計算を追加できます。

これを行う最善の方法は何ですか?

各計算を独自のスレッドで実行する必要がありますか? もしそうなら、実行中のプロセスのリストをどのように保存すればよいですか? キューを計算プロセッサに渡すにはどうすればよいですか? キューが変更されるたびに (新しい順序付けまたは新しい計算)、計算プロセッサがこれを認識できるようにするにはどうすればよいですか?

私の最初の考えは次のとおりでした。

  • CalcProcessor class
  • CalcCalculation class

の2CalcProcessorListsがありCalcCalculationsます。1 つは UI に表示される「キュー」(おそらくそれへのポインタ? またはライブで更新されることを保証する他の方法) であり、もう 1 つは現在実行中の計算のリストです。

どういうわけかCalcCalculation、独自のスレッドで実行して計算を処理し、一時停止イベントを処理できるようにする必要があります。そのため、UI で押された一時停止ボタンの情報をCalcProcessorオブジェクトに送信し、次に正しいに送信する方法が必要CalcCalculationです。

デビッド・ホープに応じて編集:

お返事をありがとうございます。

  1. はい、n 個の計算がありますが、UI で処理する計算を追加できるため、これはいつでも変更される可能性があります。

  2. とにかくデータを共有する必要はありません。アプリケーションには、同時に実行する数を指定する設定があります (つまり、任意の時点で 10、たとえばキュー内の最初の 10 - 1 が終了すると、キュー内の次の計算が処理を開始します)。

  3. 計算には、何らかのデータ ソース (データベースまたはファイル) からデータを取得し、それを分析して、そのデータに対していくつかの計算を実行することが含まれます。計算を一時停止する必要があると言うとき、スレッドを一時停止するという意味ではありません...つまり、(たとえば、アプリケーションのこの部分をまだ作成していないため) スレッドから行ごとに読み取っている場合です。データベースと現在の行の処理が完了すると一時停止するいくつかのライブ計算を実行します...そしてUIで一時停止ボタンがクリックされていないときに続行します-これは、while(notPaused)ループのように原始的なもので実行できますUI からスレッドへの一時停止情報。

4

5 に答える 5

2

ここでいくつかの質問があります:

UI とモデルを同期する方法は?

私はあなたがこれを逆にしたと思います。モデルには、UI に表示しているキューへの「ポインター」があってはなりません。代わりに、キューはモデル内にある必要があり、データバインディングを一緒に使用INotifyPropertyChangeObservableCollectionて、UI にキューを表示する必要があります。(少なくとも、それが WPF で行われる方法です。)

このようにして、モデルから直接キューを操作でき、UI に自動的に表示されます。

計算を開始して監視する方法は?

Tasksはこれに最適だと思います。Taskを使用して開始できますTask.Factory.StartNew()Taskの実行には時間がかかるように思われるため、 の使用を検討してTaskCreationOptions.LongRunningください。を使用しTaskて、計算がいつ完了したか (または例外で失敗したか) を確認することもできます。

実行中の計算を一時停止するには?

そのために使えますManualReserEventSlimTask通常は設定されますが、実行中の を一時停止したい場合は設定しますReset()。計算ではWait()、そのイベントを定期的に呼び出す必要があります。そのスレッドの計算からの協力なしに、実行中のスレッドを合理的に一時停止することはできません。

C# 5.0 を使用している場合は、PauseToken.

于 2013-02-05T14:56:32.063 に答える
0

問題を十分に分解していないことをお勧めします。これが、不満を感じている理由です。

あなたは小さく始めて、そこから積み上げる必要があります。あなたは言及しますが、実際の要件を定義しませんが、それらは...

  1. 実行できる必要がありますか?N?計算
  2. 一部は同時に実行する必要があります(これは、それらがデータを共有することを意味しますか?そうであれば、どのようにデータを共有しますか)
  3. 計算を一時停止できる必要があります(Thread.Suspendを使用しないでください。スレッドが不安定な状態になる可能性があるため、特にデータを共有している場合は悪い状態になります)。そのため、各計算に一時停止ポイントを組み込む必要があります。また、一時停止/一時停止解除を計算にどのように伝達するかを考慮する必要があります

方法に関しては、考慮すべきことがいくつかあります...

スレッドは当然の選択ですが、注意深い手入れも必要です(開始、一時停止、停止など)。

BackGroundWorkerまたはParallel.ForEachを使用することもできます

BackGroundWorkerには、ワーカーをキャンセルして進行状況を提供するためのフレームワークが含まれています(これは便利です)。

開始するための私の推奨事項は、BackGroundWorkerを使用することです。これをサブクラス化して、必要な一時停止/再開機能を追加することもできます。データ共有をどのように管理するかを決定します(少なくとも同時アクセスから保護するためにロックを使用します)。

BackGroundWorkerの制限が厳しく、スレッドを使用する必要がある場合がありますが、通常は回避できます。

より明確な要件、または試したものと機能しなかったもののサンプルを投稿していただければ、喜んでお手伝いさせていただきます。

于 2013-02-05T14:35:38.453 に答える
0

Framework 4.5では、ここでの答えはAsync APIです。これにより、スレッドを管理する必要がなくなります。詳細については、async/awaitキーワードを参照してください。

より広い観点からは、「CalcProcessor」クラスは良い考えですが、「CalcCalculation」クラスを置き換えるにはTaskオブジェクトで十分だと思います。プロセッサは、単純に列挙可能なタスクを持つことができます。プロセッサは、必要に応じてキューを管理し、そのステータスに関する情報を返すためのメソッドを公開できます。アプリケーションが最終的に結果が必要な状態に達したら、AwaitAllメソッドを使用して、すべてのタスクが完了するまでCalcProcessorのスレッドをブロックできます。

ここで実際の目標についての詳細がなければ、より良いアドバイスを与えることは困難です。

于 2013-02-05T14:31:19.943 に答える
0

オブザーバーパターンを使用して、UIに結果を表示し、変更をプロセッサーに戻すことができます。状態コマンドパターンは、計算の開始、一時停止、キャンセルに役立ちます。これらのパターンは、デザインの方法であなたの質問に素晴らしい答えを持っています。並行性は依然として問題であり、マルチスレッドの問題には答えませんが、スレッドを管理するためのより簡単な道を開きます。

于 2013-02-05T14:31:20.163 に答える
0

キューには、ヒープ データ構造 (プライオリティ キュー) を使用できます。これにより、タスクに優先順位を付けることができます。また、効果的に計算するには、スレッド プールを使用する必要があります。そして、タスクを小さな部分に分割してみてください。

于 2013-02-05T14:37:25.407 に答える