Delphiで書かれた一種のスペルチェッカーがあります。テキストを文ごとに分析します。各文を解析した後、いくつかのルールに従って間違ったアイテムに色を付けます。ユーザーはこのプロセスを中断できますが、これは重要です。サードパーティのDelphiライブラリを使用して、このプロセスを一般的に並列化するにはどうすればよいですか?現在の状態では、チェック後にその場で文の色付けをしています。したがって、ユーザーには進行状況が表示されます。
2 に答える
アルゴリズムは次のようになります。
- 複数のワーカーを作成します。
- 各ワーカーにスペルチェッカーを作成します。
- テキストをつかみ、作業単位 (単語または文) に分割します。各ワークユニットには、原文の場所を添付する必要があります。
- ワークユニットをワーカーに送信します。適切なアプローチは、ワーカーが作業単位を取得する共通キューにデータを送信することです。キューは複数のリーダーをサポートするか、ロックを使用してアクセスする必要があります。
- 各ワーカーはワーク ユニットを受け取り、スペル チェックを実行し、結果を (元のテキストの場所と共に) 所有者に返します。
- 結果を返す最も簡単な方法は、メイン スレッドにメッセージを送信することです。
- または、結果キュー (ロックを使用するか、複数のライターをサポートする必要があります) に結果を書き込むことができ、アプリケーションはそれらの結果を (タイマーまたは OnIdle ハンドラーから) ポーリングできます。
複数のスペルチェッカーがどのように辞書にアクセスするかは、別の問題です。各ワーカーにディクショナリのコピーをロードするか、ディクショナリへのアクセスをロックで保護できます (ただし、速度が低下します)。運が良ければ、ディクショナリは読み取りに対してスレッドセーフであり、ロックせずに同時クエリを実行できます。
問題に対する適切な OmniThreadLibrary 抽象化は、ParallelTask またはBackgroundWorkerのいずれかです。
並列化するには、TThread から派生した新しいクラスを作成し、そこからオブジェクトを作成し、ジョブの一部を新しいスレッドに渡して、Execute を実行し、メイン スレッドで結果を収集します。
このような:
TMySpellChecker = class(TThread)
protected
FText: String;
FResult: String;
public
procedure Execute; override;
property Text: String read FText write FText;
property Result: String read FResult write FResult;
end;
TMySpellChecker.Execute;
begin
// Analyze the text, and compute the result
end;
メインスレッドで:
NewThread := TMySpellChecker.Create(True); // Create suspended
NewThread.Text := TextSegment;
NewThread.Execute;
その後、スレッド オブジェクトはバックグラウンドで分析を行いますが、メイン スレッドは引き続き実行されます。
結果を処理するには、スレッド オブジェクトの OnTerminate イベントにハンドラーを割り当てる必要があります。
NewThread.OnTerminate := HandleMySpellCheckerTerminate;
これは、スレッド オブジェクトで Execute を実行する前に行う必要があります。
中断を可能にするための 1 つの可能性は、メイン テキストをセグメントに分割し、そのセグメントをメイン スレッドのリストに配置してから、スレッド オブジェクトを使用してセグメントを 1 つずつ分析することです。その後、各実行間の中断を許可できます。