简体   繁体   中英

How can I parallelize check spelling using Delphi?

I've got a sort of spell checker written in Delphi. It analyzes the text sentence by sentence. It encolors wrong items according to some rules after parsing each sentence. The user is able to interrupt this process, which is important. How can I parallelize this process in general using some 3rd party Delphi libraries? In the current state I've got on the fly sentence coloration after check. Thus the user sees the progress.

The algorithm would be as such:

  • Create multiple workers.
  • Create a spell-checker in each worker.
  • Grab the text and split it into work units (word or sentences). Each work unit must be accompanied with the location in original text.
  • Send work units to workers. Good approach is to send data into common queue from which workers are taking work units. Queue must either support multiple readers or you must use locking to access it.
  • Each worker takes a work unit, runs a spell-check and returns the result (together with the location in the original text) to the owner.
    • The simplest way to return a result is to send a message to the main thread.
    • Alternatively, you can write results into a result queue (which must either use locking or support multiple writers) and application can then poll those results (either from a timer or from the OnIdle handler).

How the multiple spell-checkers will access the dictionary is another problem. You can load a copy of the dictionary in each worker or you can protect access to the dictionary with a lock (but that would slow things down). If you are lucky, dictionary is thread-safe for reading and you can do simultaneous queries without locking.

Appropriate OmniThreadLibrary abstraction for the problem would be either a ParallelTask or a BackgroundWorker .

To parallelize, just create a new class descendent from TThread, create an object from it, give part of the job to the new thread, run Execute, and collect the results in the main thread.

Like this:

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;

In the main thread:

NewThread := TMySpellChecker.Create(True); // Create suspended
NewThread.Text := TextSegment;
NewThread.Execute;

The thread object will then do the analyzing in the background, while the main thread continues to run.

To handle the results, you need to assign a handler to the OnTerminate event of the thread object:

NewThread.OnTerminate := HandleMySpellCheckerTerminate;

This must be done before you run Execute on the thread object.

To allow for interruptions, one possibility is to break the main text up into segments, place the segments in a list in the main thread, and then analyze the segments one by one using the thread object. You can then allow for interruptions between each run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM