How To: Perform asynchronous handwriting recognition with the RecognizerContext object

So far, I have illustrated a couple basic handwriting recognition scenarios using the RecognizerContext object from the Tablet PC Platform SDK 1.7. First, we took a look at basic synchronous handwriting recognition, and followed that up with a demonstration of using recognition alternates. See the following posts:

https://blogs.msdn.com/gavingear/archive/2006/08/22/713189.aspx
https://blogs.msdn.com/gavingear/archive/2006/08/24/719337.aspx 

One of the drawbacks of synchronous recognition (RecognizerContext.Recognize() for instance) is the fact that you are calling a potentially time consuming method on the thread the RecognizerContext object was created on. If you create the RecognizerContext object on a Form's main thread, that means you block your UI while handwriting recognition is performed. This may not be noticeable for a small collection of strokes, but it does become an issue as the number of strokes increases (think in the 1000's here).

The Tablet PC platform addresses this issue by offering multi-threaded asynchronous handwriting recognition and corresponding methods/events. This allows your application's UI to function (including ink collection) on the main thread while handwriting recognition is performed. The application handles the appropriate event(s), and can use the recognition data when recognition is complete.

The Tablet PC Platform SDK 1.7 provides two methods that perform asynchronous handwriting recognition:

  • RecognizerContext.BackgroundRecognize()
  • RecognizerContext.BackgroundRecognizerWithAlternates()

If you want only the best recognition text for the strokes being recognized, call the former. If you need the alternates, then call the latter.

In the following sample code, I've updated our basic recognition code to use asynchronous handwriting recognition. The changes are as follows:

  1. Added a private RecognizerContext member that is resused and accessible from the event handling code
  2. Hooked up to the RecognizerContext.Recognition event to receive notification of asynchronous recognition results
  3. I now call RecognizerContext.BackgroundRecognize() in the button click handler
  4. In the RecognizerContext.Recognition event we present the recognition text to the user

Example Code:

//

// Basic Ink enabled Windows Forms application with

// handwriting recognition using RecognizerContext

// Gavin Gear - https://blogs.msdn.com/gavingear

// 08/2006

//

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Ink; // The managed Tablet PC API

namespace BasicInkApplication

{

    public partial class BasicInkApplication : Form

    {

        // The InkOverlay that we'll attach to our Form

        private InkOverlay inkOverlay;

        private RecognizerContext recognizerContext;

        public BasicInkApplication()

        {

            InitializeComponent();

            // Create an InkOverlay object that's attached to the Form

            this.inkOverlay = new InkOverlay(this);

            // Enable the InkOverlay (default is Enabled == false)

            this.inkOverlay.Enabled = true;

            // The InkOverlay needs to be disposed due to unmanaged resources

            // used by the InkOverlay

            this.FormClosing += new FormClosingEventHandler(BasicInkApplication_FormClosing);

            this.recognizerContext = new RecognizerContext();

            this.recognizerContext.Recognition +=

                new RecognizerContextRecognitionEventHandler(recognizerContext_Recognition);

        }

        void BasicInkApplication_FormClosing(object sender, FormClosingEventArgs e)

        {

  this.recognizerContext.Dispose();

            this.inkOverlay.Dispose();

        }

        // Kick off background recognition if we have strokes to recognize

        private void buttonRecognize_Click(object sender, EventArgs e)

        {

      if(this.inkOverlay.Ink.Strokes.Count > 0)

            {

                // Add the strokes collected by our InkOverlay

                this.recognizerContext.Strokes = this.inkOverlay.Ink.Strokes;

                this.recognizerContext.BackgroundRecognize();

            }

            else

            {

                MessageBox.Show("No strokes to recognize...");

            }

        }

        // Handle the Recognition event - this event is raised when

        // RecognizerContext.BackgroundRecognize() finishes

        void recognizerContext_Recognition(

            object sender,

            RecognizerContextRecognitionEventArgs e)

        {

            if (e.RecognitionStatus != RecognitionStatus.NoError)

   {

                MessageBox.Show(

                    "Error(s) were reported during recognition: " +

                    Environment.NewLine +

                    e.RecognitionStatus.ToString());

            }

            else

            {

   MessageBox.Show(

                    "Result from recognition:" +

                    Environment.NewLine +

                    e.Text);

            }

        }

    }

}

**Note that on non-Tablet PC OS platforms, you'll need to install the recognizer pack, otherwise the RecognizerContext object will throw an exception when it is instantiated. You can download the recognizer pack from the following location:

https://www.microsoft.com/downloads/details.aspx?FamilyID=080184dd-5e92-4464-b907-10762e9f918b&DisplayLang=en

There you have it- that's the basics of asynchronous recognition with the RecognizerContext.

See ya,
Gavin