進行状況をUIに報告するための最善の戦略-コールバックはどのように行われるべきか


11

ユーザーは、実行に時間がかかる拡張技術操作を開始する場合があります。このような場合、通常、現在進行中のタスクに関する情報とともに、何らかのプログレスバーを表示すると便利です。

UIとロジックレイヤーの密接な結合を避けるために、通常、何らかのプロキシを介して通信を行うことが最善です。つまり、バックエンドは独自のUI要素を操作したり、中間層と直接対話したりすることはできません。

明らかに、これを機能させるためにはどこかにコールバックが必要です。通常、2つの方法のいずれかで実装しました。

  1. 可変オブジェクトをバックエンドに渡し、進行中にバックエンドに変更を加えます。オブジェクトは、変更が発生するとフロントエンドに通知します。

  2. フォームのコールバック関数を渡すvoid f(ProgressObject)ProgressObject -> unit、バックエンドが呼び出します。この場合、バックエンドはを構築し、ProgressObject完全に受動的です。進行状況を報告するたびに新しいオブジェクトを作成する必要があると思います。

これらの方法の欠点と利点は何ですか?合意された最適な使用方法はありますか?それらの使用には異なる状況がありますか?

私が見落としている進捗状況を報告するための完全に異なるテクニックはありますか?


1
可変対不変に関して、長所と短所は他の場所と同じです。進捗オブジェクトに関しては、これは非常に軽い場合があります。それは単一の数字のような単純なものでありえます:パーセンテージ。
ロバートハーヴェイ

@RobertHarvey通常、進捗オブジェクトのサイズはUI要件に依存します。たとえば、Windowsのコピーダイアログを見てください。多くの情報が必要だと思います。
グレッグロス

1
@RobertHarveyそれは私にとってニュースです。それは何ですか?
GregRos

1
噛みます。BackgroundWorkerRHが言及していることを使用します。「進行形」などとともにカスタムクラスにラップされ、例外を通信するためのシンプルなメカニズム- BackgroundWorker設計上、別のスレッドで実行されます。.Netが提案する方法でその機能を使用する限り、それは慣用的と言えるでしょう。また、特定の言語/フレームワークのコンテキストでは、「イディオマティック」が最適かもしれません。
レーダーボブ

2
2つの方法の間に大きな違いは見当たりません。フロントエンドからバックエンドに渡されるオブジェクトは、フロントエンドの通知につながるメソッドを提供し、実際にはコールバックの機能を持っています。また、2番目のアプローチで情報の受け渡しに多かれ少なかれ複雑なパラメーターオブジェクトを使用する場合、またはいくつかの単純な値を使用する場合は、アーキテクチャの観点から違いはありません。どちらのアプローチでも、バックエンドはフロントエンドに積極的に通知しますが、違いはほんのわずかな詳細であるため、ここで説明する概念はありません。
ドックブラウン

回答:


8

可変オブジェクトをバックエンドに渡し、進行中にバックエンドに変更を加えます。オブジェクトは、変更が発生するとフロントエンドに通知します。

この点でバックエンドが通知する場合、効率のバランスを取ることは困難です。非常にスムーズな進行状況の更新を目指している場合、注意を払わずに進行状況を増分すると、操作の完了にかかる時間が2倍または3倍になることがあります。

バックエンドが呼び出すvoid f(ProgressObject)またはProgressObject-> unitという形式のコールバック関数を渡します。この場合、バックエンドはProgressObjectを構築し、完全に受動的です。進行状況を報告するたびに新しいオブジェクトを作成する必要があると思います。

ここではそれほど違いはありません。

私が見落としている進捗状況を報告するための完全に異なるテクニックはありますか?

バックエンドでアトミックな増分を行う別のスレッドでフロントエンドからポーリングします。ポーリングは有限の期間で終了する操作のためであり、フロントエンドが状態の変化を拾う可能性が高いため、特に絹のような滑らかなプログレスバーを目指している場合、ポーリングは理にかなっています。フロントエンドスレッドからのポーリングのアイデアが気に入らない場合は条件変数を検討できますが、その場合は、個々の進行状況バーの増分ごとに通知することを避けたい場合があります。


2

これは、プッシュ通知メカニズムとプル通知メカニズムの違いです。

バックエンドタスクがバックグラウンド/ワーカースレッドで実行されることが予想される場合、可変オブジェクト(pull)はUIによって繰り返しポーリングされ、同期される必要があります。

コールバック(push)は、実際に何かが変更されたときにのみUIの作業を作成します。多くのUIフレームワークには、ワーカースレッドから呼び出し可能なinvokeOnUIThreadがあり、UIスレッドでコードを実行できるため、スレッド関連の危険にさらされることなく、実際に変更を加えることができます。(しゃれ意図)

一般に、プッシュ通知は、作業を行う必要がある場合にのみ作業を行うため、推奨されます。


1
あなたの言うことは一般的に正しいと思います。ただし、この特定のケースであるプログレスバーでは、変更が急速に発生する場合があります。「進行状況」が1秒間に何度も変わる可能性があるという期待がある場合は、プルモデルを使用する方が理にかなっています。
ロボット

進行オブジェクトがコールバックを行っている可能性があるため、進行オブジェクトを送信すると、バックエンドから使用している通知メカニズムがわかりにくくなる可能性があります。覚えている限り、実際にはプルメカニズムを使用したことはありません。それを忘れていました。P
GregRos

The mutable object (the pull) will need to be repeatably polled by the UI and synchronized if you expect the back-end task to be executed in a background/worker thread.-可変オブジェクトがダイアログ自体であるか、それに対する機能するインターフェースである場合ではありません。もちろん、それはとにかくコールバックに相当します。
ロバートハーベイ

1
え?OPは、2つの異なる形式のプッシュメカニズムを明確に説明していますが、ポーリングは必要ありません。
ドックブラウン

0

AngularJSでwebsocketを使用しています。フロントエンドがメッセージを受信すると、指定されたメッセージエリアに表示され、数秒後に空白にフェードします。バックエンドでは、ステータスメッセージをメッセージキューに投稿するだけです。テキストのみを送信しますが、完了率や転送速度などの値を持つステータスオブジェクトを送信できなかった理由はありません。


0

あなたは「2つの方法」を別々の概念であるかのように述べていますが、私はそれを少し押し戻したいと思います。

  1. 可変オブジェクトをバックエンドに渡し、進行中にバックエンドに変更を加えます。オブジェクトは、変更が発生するとフロントエンドに通知します。

UIとロジックの密接な結合を避けたいと既に言っているので、渡す「可変オブジェクト」は実際にはロジックモジュールで定義されている特定のインターフェイスの実装であると想定できます。そのため、これはコールバックをプロセスに渡す別の方法に過ぎず、プロセスに関する情報を定期的に呼び出します。

利点と欠点については...

メソッド(1)の欠点は、インターフェイスを実装するクラスが一度しか実行できないことです。(異なる呼び出しで異なるジョブを実行する場合は、switchステートメントまたは訪問者パターンが必要です。)メソッド(2)を使用すると、同じオブジェクトは、バックエンドコードの呼び出しごとに異なるコールバックを使用できます。スイッチ。

メソッド(1)の強みは、メソッド(2)の複数のコールバックまたは複数のコンテキストのswitchステートメントを使用した単一のコールバックを処理するよりも、インターフェイス上に複数のメソッドを持つ方がはるかに簡単なことです。


-2

使用できる手法は非常に異なる場合があります。

私は別のシナリオで理解しようとします

  • dbへのリクエスト
  • ダウンロードファイル

dbへの単純なログイン要求(1つの要素でdbから応答することを意味します)は、レポートの進行を必要としませんが、常に別のタスクexでUIスレッドを起動できます。非同期またはバックグラウンドワーカー。ここでは、結果に対して1つのコールバックのみが必要です。

しかし、1mlnアイテムのすべての在庫を照会する場合はどうでしょうか?このクエリの完了には数分かかるので、この場合はフォームアイテム/アイテムでビジネスロジックにperportの進捗を実装する必要があります。その後、UIを更新して、コールバックのキャンセルオプションを指定できます。

ファイルのダウンロードについても同様です。ここでは、バイト単位の形式でプログレスコールバックをいつでも実装でき、httpを介したすべての通信制御は非常に一般的なパターンです。

私の個人的なアプローチでは、他のオブジェクトをエンドポイントと共有することを避けて、ビジネスの進捗ロジックをクライアントにのみ実装します。


1
これは、長所/短所に関する質問に実際には答えません。
ベニ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.