public static void Run() { // The Web Service var svc = new DictServiceSoapClient("DictServiceSoap"); var matchInDict = Observable.FromAsyncPattern <string, string, string, DictionaryWord[]>(svc.BeginMatchInDict, svc.EndMatchInDict); Func <string, IObservable <DictionaryWord[]> > suggestionForPrefix = prefix => matchInDict("wn", prefix, "prefix"); // The GUI var textBox = new TextBox(); var listBox = new ListBox { Top = textBox.Height + 10 }; var form = new Form { Controls = { textBox, listBox } }; var input = (from evt in Observable.FromEvent <EventArgs>(textBox, "TextChanged") select((TextBox)evt.Sender).Text) .Where(w => w.Length > 3) .Throttle(TimeSpan.FromSeconds(1)) .Do(x => Console.WriteLine("After Throttle:" + x)); #region Stubbing const string INPUT = "reactive"; var rand = new Random(); IObservable <string> test_input = Observable.GenerateWithTime( 3, len => len <= INPUT.Length, len => len + 1, len => INPUT.Substring(0, len), _ => TimeSpan.FromMilliseconds(rand.Next(200, 1200)) ) .ObserveOn(textBox) .Do(term => textBox.Text = term) .Throttle(TimeSpan.FromSeconds(1)); Func <string, IObservable <DictionaryWord[]> > test_suggestionForPrefix = term => Observable.Return( (from i in Enumerable.Range(0, rand.Next(0, 50)) select new DictionaryWord { Word = term + i }).ToArray()) .Delay(TimeSpan.FromSeconds(rand.Next(1, 10))); #endregion // replace with test_ to use the stubbed observables var suggestions = from term in input from words in suggestionForPrefix(term).TakeUntil(input) select words; using (suggestions.ObserveOn(listBox).Subscribe(words => { listBox.Items.Clear(); listBox.Items.AddRange((from word in words select word.Word).ToArray()); }, ex => Console.WriteLine(ex))) Application.Run(form); }
static void Main() { var txt = new TextBox(); var lst = new ListBox { Top = txt.Height + 10 }; var frm = new Form() { Controls = { txt, lst } }; #if PRODUCTION // Turn the user input into a tamed sequence of strings. var textChanged = from evt in Observable.FromEventPattern(txt, "TextChanged") select((TextBox)evt.Sender).Text; var input = textChanged .Throttle(TimeSpan.FromSeconds(1)) .DistinctUntilChanged(); #else const string INPUT = "reactive"; var rand = new Random(); var input = Observable.Generate( 3, len => len <= INPUT.Length, len => len + 1, len => INPUT.Substring(0, len), _ => TimeSpan.FromMilliseconds(rand.Next(200, 1200)) ) .ObserveOn(txt) .Do(term => txt.Text = term) .Throttle(TimeSpan.FromSeconds(1)); #endif // Bridge with the web service's MatchInDict method. var svc = new DictServiceSoapClient("DictServiceSoap"); var matchInDict = Observable.FromAsyncPattern <string, string, string, DictionaryWord[]> (svc.BeginMatchInDict, svc.EndMatchInDict); #if PRODUCTION Func <string, IObservable <DictionaryWord[]> > matchInWordNetByPrefix = term => matchInDict("wn", term, "prefix"); #else Func <string, IObservable <DictionaryWord[]> > matchInWordNetByPrefix = term => Observable.Return ( (from i in Enumerable.Range(0, rand.Next(0, 50)) select new DictionaryWord { Word = term + i }) .ToArray() ).Delay(TimeSpan.FromSeconds(rand.Next(1, 10))); #endif // The grand composition connecting the user input with the web service. var res = (from term in input select matchInWordNetByPrefix(term)) .Switch(); // Synchronize with the UI thread and populate the ListBox or signal an error. using (res.ObserveOn(lst).Subscribe( words => { lst.Items.Clear(); lst.Items.AddRange((from word in words select word.Word).ToArray()); }, ex => { MessageBox.Show( "An error occurred: " + ex.Message, frm.Text, MessageBoxButtons.OK, MessageBoxIcon.Error ); })) { Application.Run(frm); } // Proper disposal happens upon exiting the application. }