Go on, suggest something

Of course, to get more a grip on a new framework, it is always good to try to write something using it. In one of videos on Rx, the presentors talk about expressing a suggestions framework using a LINQ query. For this, we’ll need a textbox, textBox1, and a ListBox, listBox1. When you type into the textbox, suggestions will be generated. These will take the form of the original text with ascending integers appended to the end with a new suggestion being added every two seconds. When the text changes, we’d like the suggestions process to be restarted.
 
In a second we’ll look at the code for an object that raises the suggestions. We’ll use an object called Suggestor, which will take the initial string and return an array of suggestions with these returned arrays getting an extra element every two seconds. First, we’ll do the code in the form to hook the suggestions into the components.
 
// Grab the synchronization context for the windows form, so that all work is done ont he right thread

SynchronizationContext context = SynchronizationContext.Current;

// Notice changes to the textbox
IObservable<Event<EventArgs>> textChanged = Observable.FromEvent<EventArgs>(textBox1, "TextChanged");

// Get a stream of new values of the textbox
var
data = from _ in textChanged select textBox1.Text;

// Grab the groups of suggestions, starting a new Suggestor whenever the string in the textbox changes.
var suggestion =
 
from start in data
 
from item in new Suggestor(start).Until(textChanged)
 
select item;

// Set the new suggestions into the listbox
suggestion.Subscribe(
 
delegate(string[] x)
 
{
   
context.Post(newValue => listBox1.DataSource=newValue, x);
 
});

The code for the windows form looks quite straight-foward. All the interesting code to do with IObservable is hidden in the Suggestor object. This uses a threadpool thread to run code which returns the new suggestions array every two seconds. When the result of the Subscribe is disposed, the thread can be shut down.

class Suggestor : IObservable<string[]>
{
 
readonly string m_Initial;

  public Suggestor(string initial)
  {
    m_Initial = initial;
  }

  public IDisposable Subscribe(IObserver<string[]> observer)
  {
   
Generator generator = new Generator(observer, m_Initial);
   
ThreadPool.QueueUserWorkItem(delegate { generator.DoWork(); });
   
return generator;
  }

  class Generator : IDisposable
 
{
   
volatile IObserver<string[]> m_Observer;
   
readonly string m_Initial;
   
readonly object m_Lock = new object();

    public Generator(IObserver<string[]> observer, string initial)
    {
      m_Observer = observer;
      m_Initial = initial;
     
Console.WriteLine("Generator started " + m_Initial);
    }

    public void Dispose()
    {
     
lock (m_Lock)
      {
        m_Observer =
null;
       
Console.WriteLine("Dispose on " + m_Initial);
      }
    }

    public void DoWork()
    {
     
List<string> suggestions = new List<string>();
      suggestions.Add(m_Initial);
     
for(int index = 0; ; index++)
      {
       
lock (m_Lock)
        {
          suggestions.Add(m_Initial + index);
         
if (m_Observer == null)
           
break;
         
Console.WriteLine("Next on " + m_Initial);
          m_Observer.OnNext(suggestions.ToArray());
       
}
       
Thread.Sleep(2000);
      }
   
Console.WriteLine("Generator stopped " + m_Initial);
    }
  }
}

 
 
Advertisements
This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s