<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.atalasoft.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rick Minerich's Development Wonderland : delegates</title><link>http://www.atalasoft.com/cs/blogs/rickm/archive/tags/delegates/default.aspx</link><description>Tags: delegates</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>A Speedy Alternative to F# DelegateEvents</title><link>http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx</link><pubDate>Fri, 04 Jun 2010 16:19:58 GMT</pubDate><guid isPermaLink="false">647108ca-f046-4d8d-9feb-a7fbd2049b37:20757</guid><dc:creator>RickM</dc:creator><slash:comments>4</slash:comments><comments>http://www.atalasoft.com/cs/blogs/rickm/comments/20757.aspx</comments><wfw:commentRss>http://www.atalasoft.com/cs/blogs/rickm/commentrss.aspx?PostID=20757</wfw:commentRss><wfw:comment>http://www.atalasoft.com/cs/blogs/rickm/rsscomments.aspx?PostID=20757</wfw:comment><description>&lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;DelegateEvents use DynamicInvoke under the hood and so can be slow when trigged frequently.&amp;#160; As we have an existing model which requires an event interface, this was was causing our F# implementation to be a bit slower than the C# we were comparing it to.&amp;#160; Thankfully, F# allows you to implement your own eventing via IDelegateEvent.&amp;#160; With a standard Invoke version of DelegateEvent provided by James Margetson, our implementation in F# is running at equivalent speed to C#.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The other day I was working with &lt;a href="http://www.atalasoft.com/cs/blogs/stevehawley/"&gt;Steve&lt;/a&gt; on trying to discover why a particular segment of apparently equivalent code was running ~25% slower in F# when compared to C#.&amp;#160; We broke out &lt;a href="http://www.automatedqa.com/products/aqtime/"&gt;AQTime&lt;/a&gt; and did a line by line release-mode profile.&amp;#160; The frequent triggering of a &lt;a href="http://msdn.microsoft.com/en-us/library/ee370450.aspx"&gt;DelegateEvent&lt;/a&gt; immediately jumped out as the cause.&amp;#160; &lt;/p&gt;  &lt;p&gt;Needless to say, I was a bit concerned.&amp;#160; What could be causing this slow eventing in my favorite language?&amp;#160; After a brief review of the generated IL, nothing in particular seemed fishy.&amp;#160; So, I quickly built a sample and sent it off to my favorite language team.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The contents of the F# library assembly:&lt;/strong&gt;&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dc45fc3f-9c89-49d1-bef1-39b6ee119d05" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;overflow:auto;padding:2px 5px;white-space:nowrap;"&gt;&lt;span style="color:#0000ff;"&gt;type&lt;/span&gt; FsEventClass(num) =&lt;br&gt;     &lt;span style="color:#0000ff;"&gt;let&lt;/span&gt; event = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; DelegateEvent&amp;lt;System.EventHandler&amp;lt;System.EventArgs&amp;gt;&amp;gt;()&lt;br&gt;     &lt;br&gt;     [&amp;lt;CLIEvent&amp;gt;]&lt;br&gt;     &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; this.Event = event.Publish&lt;br&gt;             &lt;br&gt;     &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; this.Run () = &lt;br&gt;         &lt;span style="color:#0000ff;"&gt;let&lt;/span&gt; args = [| this :&amp;gt; obj ; System.EventArgs.Empty :&amp;gt; obj |]&lt;br&gt;         &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; i &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; 1 .. num &lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;&lt;br&gt;             args.[1] &amp;lt;- &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; System.EventArgs() :&amp;gt; obj&lt;br&gt;             event.Trigger( args )&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;And this, the C# client:&lt;/strong&gt;&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2dcf6ed5-ad9a-4cde-afbc-7e65fb9a81a1" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;overflow:auto;padding:2px 5px;white-space:nowrap;"&gt;&lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br&gt; {&lt;br&gt;     &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; iters = 1000000;&lt;br&gt; &lt;br&gt;     &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt; fsStart = &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;.Now;&lt;br&gt;     &lt;span style="color:#2b91af;"&gt;FSharpEventingLib&lt;/span&gt;.&lt;span style="color:#2b91af;"&gt;FsEventClass&lt;/span&gt; fs = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;FSharpEventingLib&lt;/span&gt;.&lt;span style="color:#2b91af;"&gt;FsEventClass&lt;/span&gt;(iters);&lt;br&gt;     &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; fsCalled = 0;&lt;br&gt;     fs.Event += (s, a) =&amp;gt; fsCalled++;&lt;br&gt;     fs.Run();&lt;br&gt;     &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt; fsEnd = &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;.Now;&lt;br&gt;     &lt;span style="color:#2b91af;"&gt;TimeSpan&lt;/span&gt; fsTime = fsEnd - fsStart;&lt;br&gt;     System.&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;.Format(&lt;span style="color:#a31515;"&gt;&amp;quot;F# took: {0} when called {1} times&amp;quot;&lt;/span&gt;, fsTime, fsCalled)); &lt;br&gt; }&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Finally, the program output:&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;F# took: 00:00:05.6830000 when called 1000000 times&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As it turns out, the F#’s current &lt;a href="http://msdn.microsoft.com/en-us/library/ee370450.aspx"&gt;DelegateEvent&lt;/a&gt; uses a DynamicInvoke under the hood and that can slow things down quite a bit.&amp;#160; This won’t be important in most cases as Event is implemented with a standard Invoke.&amp;#160; However, in our case we had to fit to an existing C# model and so needed to do an event trigger for each resulting scanline of an image.&lt;/p&gt;  &lt;p&gt;A big thanks to James Margetson of the F# Team for the following fast replacement for DelegateEvent.&amp;#160; Within same day I had mentioned my issue he had this solution for me.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The new library contents:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:75d3ea67-e88d-4308-bffc-de81cd96ed5f" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background-color:#ffffff;overflow:auto;padding:2px 5px;white-space:nowrap;"&gt;&lt;span style="color:#0000ff;"&gt;type&lt;/span&gt; FastDelegateEvent() =&lt;br&gt;     &lt;span style="color:#0000ff;"&gt;let&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;mutable&lt;/span&gt; multicast : System.EventHandler = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;br&gt; &lt;br&gt;     &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; x.Trigger(sender:obj,args:System.EventArgs) =&lt;br&gt;         &lt;span style="color:#0000ff;"&gt;match&lt;/span&gt; multicast &lt;span style="color:#0000ff;"&gt;with&lt;/span&gt;&lt;br&gt;         | &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;-&amp;gt;&lt;/span&gt; ()&lt;br&gt;         | d &lt;span style="color:#0000ff;"&gt;-&amp;gt;&lt;/span&gt; d.Invoke(sender,args)   &lt;span style="color:#008000;"&gt;// DelegateEvent used: d.DynamicInvoke(args) |&amp;gt; ignore&lt;/span&gt;&lt;br&gt;  &lt;br&gt;     &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; x.Publish =&lt;br&gt;         { &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; IDelegateEvent&amp;lt;System.EventHandler&amp;gt; &lt;span style="color:#0000ff;"&gt;with&lt;/span&gt;&lt;br&gt;             &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; x.AddHandler(d) =&lt;br&gt;                 multicast &amp;lt;- System.Delegate.Combine(multicast, d) :?&amp;gt; System.EventHandler&lt;br&gt;             &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; x.RemoveHandler(d) =&lt;br&gt;                 multicast &amp;lt;- System.Delegate.Remove(multicast, d)  :?&amp;gt; System.EventHandler }&lt;br&gt; &lt;br&gt; &lt;span style="color:#0000ff;"&gt;type&lt;/span&gt; FsFastEventClass(num) =&lt;br&gt;    &lt;span style="color:#0000ff;"&gt;let&lt;/span&gt; event = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FastDelegateEvent()&lt;br&gt; &lt;br&gt;    [&amp;lt;CLIEvent&amp;gt;]&lt;br&gt;    &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; this.Event = event.Publish&lt;br&gt; &lt;br&gt;    &lt;span style="color:#0000ff;"&gt;member&lt;/span&gt; this.Run () =&lt;br&gt;        &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; i &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; 1 .. num &lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;           &lt;br&gt;            event.Trigger(this, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; System.EventArgs())&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The program output with FastDelegateEvent:&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;F# took: 00:00:00.0390000 when called 1000000 times&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;This new event class completely resolved our issue.&amp;#160; With it our F# version is just as fast, if not faster, than the C# equivalent.&amp;#160; &lt;/p&gt;
&lt;div class = "shareblock"&gt;&lt;strong&gt;Share this post:&lt;/strong&gt; &lt;a href = "mailto:?body=Thought you might like this: http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;;subject=A+Speedy+Alternative+to+F%23+DelegateEvents" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;;title=A+Speedy+Alternative+to+F%23+DelegateEvents" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;;phase=2" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;title=A+Speedy+Alternative+to+F%23+DelegateEvents" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;;title=A+Speedy+Alternative+to+F%23+DelegateEvents" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;;mkt=en-us&amp;amp;;url=http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx&amp;amp;;title=A+Speedy+Alternative+to+F%23+DelegateEvents&amp;amp;;top=1" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2010/06/04/a-speedy-alternative-to-f-delegateevents.aspx"&gt;live it!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=20757" width="1" height="1"&gt;</description><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/delegates/default.aspx">delegates</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/fsharp/default.aspx">fsharp</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/interop/default.aspx">interop</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/DelegateEvent/default.aspx">DelegateEvent</category></item><item><title>Processes in .NET Part 3 – Interfacing With Simple Console Programs by Example, Tesseract OCR</title><link>http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx</link><pubDate>Thu, 08 Jan 2009 11:00:00 GMT</pubDate><guid isPermaLink="false">647108ca-f046-4d8d-9feb-a7fbd2049b37:16617</guid><dc:creator>RickM</dc:creator><slash:comments>5</slash:comments><comments>http://www.atalasoft.com/cs/blogs/rickm/comments/16617.aspx</comments><wfw:commentRss>http://www.atalasoft.com/cs/blogs/rickm/commentrss.aspx?PostID=16617</wfw:commentRss><wfw:comment>http://www.atalasoft.com/cs/blogs/rickm/rsscomments.aspx?PostID=16617</wfw:comment><description>&lt;p&gt;Did you know that .NET provides an easy way to interact and control console programs?&amp;#160; In this article I will walk you through this process by creating a wrapper class for &lt;a href="http://code.google.com/p/tesseract-ocr"&gt;Google’s Tesseract OCR&lt;/a&gt; application.&amp;#160; At the end of this post, I will provide a complete WinForms-based frontend for Google’s Tesseract OCR Engine. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Initial Tesseract Setup&lt;/h3&gt;  &lt;p&gt;First, download the &lt;a href="http://tesseract-ocr.googlecode.com/files/tesseract-2.01.tar.gz"&gt;precompiled version&lt;/a&gt; from the Tesseract &lt;a href="http://code.google.com/p/tesseract-ocr/downloads/list"&gt;download site&lt;/a&gt;.&amp;#160; As 2.03 does not yet have a precompiled version available we will be using 2.01.&amp;#160; You will also need to download the corresponding language files for Tesseract.&amp;#160; I will be using the &lt;a href="http://tesseract-ocr.googlecode.com/files/tesseract-2.00.eng.tar.gz"&gt;English language dataset&lt;/a&gt;.&amp;#160; Extract your dataset archive into the same directory you placed your precompiled binaries.&amp;#160; Please insure that all directory structure remains intact, as otherwise Tesseract will not work. &lt;/p&gt;  &lt;p&gt;Unfortunately, the precompiled version does not include any of the help, so if you wish to read up on how to use Tesseract you need to view the &lt;a href="http://code.google.com/p/tesseract-ocr/wiki/ReadMe"&gt;online documentation&lt;/a&gt;.&amp;#160; Only one line from the documentation is necessary for our purposes: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;tesseract &amp;lt;image.tif&amp;gt; &amp;lt;output&amp;gt; [-l langid]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Here we see that we Tesseract takes three parameters, one optional.&amp;#160; The first being a tiff file to perform the OCR on, the second being an output text file and the final, optional, parameter being a language identifier.&amp;#160; Please note that whatever filename you specify as output will actually have .txt appended internally by Tesseract.&amp;#160; As for this simple example, I’m going to ignore the langid parameter as Tesseract defaults to English.&amp;#160; I also know from my own personal experience implementing Tesseract support in our &lt;a href="http://www.atalasoft.com/products/dotimage/ocr/default.aspx"&gt;DotImage OCR Toolkit&lt;/a&gt;, by default Tesseract only supports 1 bit per pixel uncompressed Tiffs.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Basics of Running Tesseract&lt;/h3&gt;  &lt;p&gt;You would think that this is a particularly simple case as Tesseract only needs to be passed in parameters and requires no flow control.&amp;#160; Ideally, we will simply leverage the Process class to control how Tesseract is launched and read from it’s output.&amp;#160; Initially, this is only a small jump from what we learned in &lt;a href="http://www.atalasoft.com/cs/blogs/rickm/archive/2008/12/16/processes-in-net-part-2-safely-closing-processes.aspx"&gt;Processes in .NET Part 2&lt;/a&gt;.&amp;#160; The only real difference here is that instead of using Verbs we are specifying behavior through the &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.arguments.aspx"&gt;ProcessStartInfo’s Arguments property&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: Process tessProc = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Process();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: tessProc.StartInfo.WorkingDirectory = @&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3: tessProc.StartInfo.FileName = @&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess\tesseract.exe&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4: tessProc.StartInfo.Arguments = &amp;quot;&lt;span style="color:#8b0000;"&gt;input.tif output&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5: tessProc.Start();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6: tessProc.WaitForExit();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7: &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; output = File.ReadAllText(@&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess\output.txt&lt;/span&gt;&amp;quot;);&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Unfortunately, while this very simple example will work in many cases, this is not one.&amp;#160; This is because Tesseract.exe secretly launches a separate process and immediately exits.&amp;#160; This makes the WaitForExit() call look like it was successful but, as OCR takes a while, when you try to read from the output file it will either not yet exist or it will be locked for writing by the Tesseract process.&lt;/p&gt;

&lt;p&gt;There are many different ways to approach this problem.&amp;#160; In this case an easy method would be to try repeatedly to access Tesseract’s log file using a timeout to ensure our program doesn't lock up.&amp;#160; Successful or not, the log file is always written right before the process terminates.&amp;#160; Additionally, in the case of failure, it has information about what happened.&lt;/p&gt;

&lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: Process tessProc = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Process();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: tessProc.StartInfo.WorkingDirectory = @&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3: tessProc.StartInfo.FileName = @&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess\tesseract.exe&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4: tessProc.StartInfo.Arguments = &amp;quot;&lt;span style="color:#8b0000;"&gt;input.tif output&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5: tessProc.Start();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7: &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; timeout = 10000, increment = 1000;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  8: &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; logtext = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  9: &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; ((timeout -= increment) &amp;gt; 0)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 10: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 11:     &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 12:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 13:         logtext = File.ReadAllText(@&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess\tesseract.log&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 14:         &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 15:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 16:     &lt;span style="color:#0000ff;"&gt;catch&lt;/span&gt; (IOException)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 17:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 18:         System.Threading.Thread.Sleep(increment);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 19:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 20: }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 21: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 22: &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; output;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 23: &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (logtext != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; !logtext.Contains(&amp;quot;&lt;span style="color:#8b0000;"&gt;Error&lt;/span&gt;&amp;quot;))
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 24:     output = File.ReadAllText(@&amp;quot;&lt;span style="color:#8b0000;"&gt;C:\Tess\output.txt&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 25: &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 26:     output = &amp;quot;&lt;span style="color:#8b0000;"&gt;&lt;/span&gt;&amp;quot;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 27: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 28: &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; output;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This example only provides the very basics of what is necessary to run Tesseract and get a result.&amp;#160; In order to use Tesseract in a robust and extensible way, we will need to build a complete wrapper class.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Designing a Wrapper Class&lt;/h3&gt;

&lt;p&gt;Tesseract has a number of quirks which makes it somewhat annoying to deal with, at least when compared with most other command line applications.&amp;#160; It’s important to be on the lookout for these kinds of small quirks when building an interface to an application.&amp;#160; For completeness, I’ll list what I’ve found for Tesseract here along with solutions.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tesseract always appends .txt to the output filename. 
    &lt;ul&gt;
      &lt;li&gt;As above, append “.txt” when you read the output file. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Tesseract launches a second background process which does the work. 
    &lt;ul&gt;
      &lt;li&gt;As above, I chose wait on output with a timeout.&amp;#160; However, this technique does not allow for multiple instances of the same Tesseract process as the log file is shared.&amp;#160; As of right now I perform OCR in a lock in order to prevent multiple executions at the same time. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Tesseract does not like paths with spaces. 
    &lt;ul&gt;
      &lt;li&gt;Copy locally before processing. This way Tesseract never has to leave it’s working directory. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Tesseract provides no useful feedback outside of the log file. 
    &lt;ul&gt;
      &lt;li&gt;As above, wait on and parse the file when it becomes available.&amp;#160; Be sure to delete the file when you are finished.&amp;#160; Otherwise you may run into a situation where you are parsing old log data. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface essentially boils down to the two following methods.&amp;#160; The complexity in the interface stems from the very properties we just enumerated.&amp;#160;&amp;#160; &lt;/p&gt;

&lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TesseractWrapper
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; TesseractWrapper(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; programLoc)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5:         DirectoryInfo dinfo = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; DirectoryInfo(programLoc);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6:         ValidateTesseractDirectory(dinfo);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7:         _tesseractLocation = dinfo.FullName;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  8:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  9: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 10:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; ExtractText(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; imageFile)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 11:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 12:         &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (!File.Exists(imageFile))
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 13:             &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ArgumentException(&amp;quot;&lt;span style="color:#8b0000;"&gt;Specified file must exist.&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 14: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 15:         &lt;span style="color:#008000;"&gt;//Init Instance Timeout Variable&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 16:         _timeLeft = _tessTimeout;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 17: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 18:         &lt;span style="color:#0000ff;"&gt;lock&lt;/span&gt; (_lockObj)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 19:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 20:             Process tessProc = BuildTesseractProcess();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 21:             &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; RunOCR(tessProc, imageFile);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 22:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 23:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 24: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 25:     &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; RunOCR(Process tessProc, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; imagePath)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 26:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 27:         &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; imgParameter, outputParameter, outputText;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 28: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 29:         &lt;span style="color:#008000;"&gt;//Temporary Files, Be Sure To Clean Up&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 30:         &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; textOutputPath, logPath, tempImagePath; 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 31: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 32:         GenerateFilePathsAndParameters(&lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; imgParameter, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; tempImagePath, 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 33:             &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; outputParameter, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; textOutputPath, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; logPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 34: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 35:         &lt;span style="color:#008000;"&gt;//Ensure no previous log file is hanging around.&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 36:         CleanUpFiles(logPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 37: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 38:         &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 39:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 40:             &lt;span style="color:#008000;"&gt;//Copy image locally to avoid issues with spaces in paths.&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 41:             File.Copy(imagePath, tempImagePath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 42: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 43:             LaunchTesseract(tessProc, imgParameter, outputParameter);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 44: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 45:             &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; logText = ReadFileWithInstanceTimeout(logPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 46:             CheckTesseractLogTextAndThrowOnError(logText);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 47:             outputText = ReadFileWithInstanceTimeout(textOutputPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 48:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 49:         &lt;span style="color:#0000ff;"&gt;finally&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 50:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 51:             CleanUpFiles(tempImagePath, textOutputPath, logPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 52:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 53: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 54:         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; outputText;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 55:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 56: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 57:     &lt;span style="color:#008000;"&gt;/* Download the full source to see private members and methods */&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 58: }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Overall, it’s not exactly what I would call production quality but it’s acceptable for when I need to quickly test a file in Tesseract. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;An Asynchronous Wrapper for Easy WinForms Integration&lt;/h3&gt;

&lt;p&gt;Once you have all of the little quirks of your application covered, the only issue left is that calling your ExtractText method leaves your application locked up for it has returned.&amp;#160; The best way to deal with this is to use an DynamicInvoke on a delegate and managing the update to your console application via a callback.&amp;#160; To make this easy I wrote an asynchronous child class.&lt;/p&gt;

&lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; AsyncTesseractWrapper : TesseractWrapper
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; AsyncRunTesseract(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; imageFile)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5:         AsyncRunTesseract(imageFile, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  8:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; AsyncRunTesseract(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; imageFile, TesseractOcrComplete callback)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  9:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 10:         &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_runner != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; !IsCompleted)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 11:             &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ApplicationException(&amp;quot;&lt;span style="color:#8b0000;"&gt;Please wait until the previous Async call is complete before running another.&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 12:        
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 13:         ResetAsyncFields();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 14:         _completeCallback = callback;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 15:         _runner = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TesseractRunner(PerformOCRExceptionCatcher);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 16:         _asyncResult = _runner.BeginInvoke(imageFile, AsyncCallback, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 17:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 18: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 19:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; IsCompleted 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 20:     { 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 21:         &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt; 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 22:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 23:             &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _asyncResult == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; ? &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt; : _asyncResult.IsCompleted;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 24:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 25:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 26: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 27:     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; GetAsyncResult()
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 28:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 29:         &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_lastException != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; _lastException;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 30:         &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_asyncResult == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 31:         &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_output == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) _output = _runner.EndInvoke(_asyncResult);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 32:         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _output;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 33:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 34:     
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 35:     &lt;span style="color:#008000;"&gt;/* Download the full source to see private members and methods */&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 36: }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;With this in place, it’s a simple matter to call Tesseract from a WinForms application:&lt;/p&gt;

&lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: _wrapper = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AsyncTesseractWrapper(tesseractPath);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3: &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5:     _wrapper.AsyncRunTesseract(dialog.FileName);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6:     ocrResultCheckTimer.Enabled = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7: } 
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  8: &lt;span style="color:#0000ff;"&gt;catch&lt;/span&gt; (WrapperException ex)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  9: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 10:     MessageBox.Show(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, ex.Message);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 11: }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Because WinForms controls don’t like it when you try to change their values from an external thread, it is necessary to poll our asynchronous class instead of using a callback.&amp;#160; I implemented this using a simple form timer.&lt;/p&gt;

&lt;pre style="border-right:#cecece 1px solid;padding-right:5px;border-top:#cecece 1px solid;padding-left:5px;min-height:40px;padding-bottom:5px;overflow:auto;border-left:#cecece 1px solid;width:480px;padding-top:5px;border-bottom:#cecece 1px solid;background-color:#fbfbfb;"&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  1: &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; ocrResultCheckTimer_Tick(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, EventArgs e)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  2: {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  3:     &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_wrapper.IsCompleted)
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  4:     {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  5:         &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  6:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  7:             richTextBox1.Text = _wrapper.GetAsyncResult();
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt;  8:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt;  9:         &lt;span style="color:#0000ff;"&gt;finally&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 10:         {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 11:             ocrResultCheckTimer.Enabled = &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 12:         }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#fbfbfb;"&gt; 13:     }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,'Courier New',courier,monospace;background-color:#ffffff;"&gt; 14: }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Well, that finishes up my walkthrough on writing a wrapper class for Tesseract’s console build.&amp;#160; This of course is much different than how I implemented Tesseract support in our toolkit.&amp;#160; For that I wrote hooks into the actual DLL file.&amp;#160; If you have any questions, or have a better way to implement part of this project, please leave a comment.&amp;#160; In this way, everyone can benefit from your knowledge. &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="wlWriterEditableSmartContent" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:c2a81aa4-087a-48d9-84a6-d2ad84738f56" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://www.atalasoft.com/cs/blogs/rickm/TesseractLancherFiles_0052A38E.zip" target="_self"&gt;Download The Tesseract Console Wrapper and WinForms Solution&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class = "shareblock"&gt;&lt;strong&gt;Share this post:&lt;/strong&gt; &lt;a href = "mailto:?body=Thought you might like this: http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;;subject=Processes+in+.NET+Part+3+%e2%80%93+Interfacing+With+Simple+Console+Programs+by+Example%2c+Tesseract+OCR" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;;title=Processes+in+.NET+Part+3+%e2%80%93+Interfacing+With+Simple+Console+Programs+by+Example%2c+Tesseract+OCR" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;;phase=2" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;title=Processes+in+.NET+Part+3+%e2%80%93+Interfacing+With+Simple+Console+Programs+by+Example%2c+Tesseract+OCR" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;;title=Processes+in+.NET+Part+3+%e2%80%93+Interfacing+With+Simple+Console+Programs+by+Example%2c+Tesseract+OCR" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;;mkt=en-us&amp;amp;;url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx&amp;amp;;title=Processes+in+.NET+Part+3+%e2%80%93+Interfacing+With+Simple+Console+Programs+by+Example%2c+Tesseract+OCR&amp;amp;;top=1" target="_blank" title = "Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/01/08/processes-in-net-part-3-manipulating-external-processes.aspx"&gt;live it!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=16617" width="1" height="1"&gt;</description><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/delegates/default.aspx">delegates</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/concurrency/default.aspx">concurrency</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/object+oriented/default.aspx">object oriented</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/.NET/default.aspx">.NET</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/Tutorials/default.aspx">Tutorials</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/processes/default.aspx">processes</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/ocr/default.aspx">ocr</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/design/default.aspx">design</category></item><item><title>Increasing the Size of your Stack (.NET Memory Management: Part 3) </title><link>http://www.atalasoft.com/cs/blogs/rickm/archive/2008/04/22/increasing-the-size-of-your-stack-net-memory-management-part-3.aspx</link><pubDate>Tue, 22 Apr 2008 17:45:00 GMT</pubDate><guid isPermaLink="false">647108ca-f046-4d8d-9feb-a7fbd2049b37:13734</guid><dc:creator>RickM</dc:creator><slash:comments>5</slash:comments><comments>http://www.atalasoft.com/cs/blogs/rickm/comments/13734.aspx</comments><wfw:commentRss>http://www.atalasoft.com/cs/blogs/rickm/commentrss.aspx?PostID=13734</wfw:commentRss><wfw:comment>http://www.atalasoft.com/cs/blogs/rickm/rsscomments.aspx?PostID=13734</wfw:comment><description>In the previous article I discussed a few of the benefits of stack allocation as well as a couple of C# keywords which help you to leverage those benefits. However, the one megabyte default stack size is too small for stack allocation to be used with...(&lt;a href="http://www.atalasoft.com/cs/blogs/rickm/archive/2008/04/22/increasing-the-size-of-your-stack-net-memory-management-part-3.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=13734" width="1" height="1"&gt;</description><enclosure url="http://www.atalasoft.com/cs/blogs/rickm/attachment/13734.ashx" length="6659" type="application/x-zip-compressed" /><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/programming/default.aspx">programming</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/delegates/default.aspx">delegates</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/code/default.aspx">code</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/optimization/default.aspx">optimization</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/.NET/default.aspx">.NET</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/Tutorials/default.aspx">Tutorials</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/memory/default.aspx">memory</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/stack/default.aspx">stack</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/allocation/default.aspx">allocation</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/kernel32/default.aspx">kernel32</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/pinvoke/default.aspx">pinvoke</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/unsafe/default.aspx">unsafe</category></item><item><title>The Evolution of Lambda Functions in C#</title><link>http://www.atalasoft.com/cs/blogs/rickm/archive/2008/03/20/the-evolution-of-lambda-functions-in-c.aspx</link><pubDate>Thu, 20 Mar 2008 14:24:00 GMT</pubDate><guid isPermaLink="false">647108ca-f046-4d8d-9feb-a7fbd2049b37:13512</guid><dc:creator>RickM</dc:creator><slash:comments>0</slash:comments><comments>http://www.atalasoft.com/cs/blogs/rickm/comments/13512.aspx</comments><wfw:commentRss>http://www.atalasoft.com/cs/blogs/rickm/commentrss.aspx?PostID=13512</wfw:commentRss><wfw:comment>http://www.atalasoft.com/cs/blogs/rickm/rsscomments.aspx?PostID=13512</wfw:comment><description>Howard Dierking over at MSDN has a really interesting Blog post entitled " Lambda, Lambda, Lambda! " in which he described the evolution of the lambda function in C#. It seems fairly simple on the surface: 1.0 Introduced Delegates, 2.0 Introduced Anonymous...(&lt;a href="http://www.atalasoft.com/cs/blogs/rickm/archive/2008/03/20/the-evolution-of-lambda-functions-in-c.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=13512" width="1" height="1"&gt;</description><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/programming/default.aspx">programming</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/delegates/default.aspx">delegates</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/anonymous+functions/default.aspx">anonymous functions</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://www.atalasoft.com/cs/blogs/rickm/archive/tags/lamba/default.aspx">lamba</category></item></channel></rss>