HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Processing input in background while user is typing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
whilebackgrounduserinputtypingprocessing

Problem

Use case

A GUI with 2 controls:

  • An input control for text (a DNA sequence) that should be analyzed



  • A result control that displays the analyzing result of the entered text



The analysis takes 2-3 seconds and should start as soon as the text in the input control is changing. The shown result should always match the actual text in the input field.

Problem

If the user types text, it changes multiple times within the processing time of the analysis. Starting multiple processing tasks parallel is not an option.

Solution

My approach for solving the problem above:

  • An 'ItemProcessor' gets the input and process it in background.



  • If a new item was added whereas another item is processing, the new item is 'stored' for subsequent processing.



  • If another item is already stored for subsequent processing, it will be overwritten.



  • The result is returned only, of no item for subsequent processing is available anymore.



Implementation:

```
public class LastItemProcessor
{
private readonly Func> Process;
private readonly Action OnProcessingStartedAction;
private readonly Action OnProcessingFinishedAction;
private readonly Action> OnLastItemProcessedAction;
private TInput myInput;
private bool myIsLastItemFlag = true;
private bool myIsProcessing = false;
private readonly object myLock = new object();

public LastItemProcessor(Func> process,
Action> onLastItemProcessedAction,
Action onProcessingStartedAction = null,
Action onProcessingFinishedAction = null)
{
process.Ensure(nameof(process)).IsNotNull();
onLastItemProcessedAction.Ensure(nameof(onLastItemProcessedAction)).IsNotNull();

Process = process;
OnProcessingStartedAction = onProcessingStartedAction;
OnProcessingFinishedAction = onProcessingFinishedAction;
OnLastItemProcessedAction = onLastItemProcessedAction;
}

public void ProcessItem(TInput input)
{
lock (myLock)
{

Solution

There are two alternatives:

  • Reactive extensions with Throttle + Switch combo. It will take care of throttling text changes, overriding previous results and scheduling tasks. Rx API is not for the faint-hearted though. See: https://stackoverflow.com/a/22924151/1386995 .



  • TPL Dataflow with BroadcastBlock + ActionBlock combo. It will take care about everything except for throttling. You will have to initialize those blocks with correct buffer sizes and degrees of parallelism.



Also note, that Dataflow blocks can be converted to Rx observables with extension methods, so you can combine those frameworks.

As for your implementation:

-
if


The shown result should always match the actual text in the input
field.

Then you should probably cancel incomplete processing when input changes. If you are going to discard the result anyway, then there is no reason to wait for completion. 3s is a lot of time.

-
I don't have a clear understanding on how recursion works with async/await. It can behave differently. Maybe you should take extra precautions to make sure that stack can not overflow.

-
I'm not a fan of my prefixes. But that's a personal preference.

-
myIsLastItemFlag name is a bit confusing. I think something like myIsInputChanged would do a better job at explaining what this flag is for. Also Flag postfix is unnecessary, Is prefix already hints, that it is a bool field.

Context

StackExchange Code Review Q#163170, answer score: 2

Revisions (0)

No revisions yet.