1

I am using a WPF TextBox to perform server side spell checking in a web application. I know it's a naughty thing to add the PresentationFramework to a web app hosted in IIS, but I did it anyway. Now I'm paying the price.

I'm doing something like this:

var spellCheckTextBox = new TextBox {
   Text = text
};

int errorIndex = spellCheckTextBox.GetNextSpellingErrorCharacterIndex(startPosition, LogicalDirection.Forward);

To do this I have to call the method in an STA as this article outlines.

I am getting an Win32Exception: The operation completed successfully exception, I think this is because I have exceeded the maximum number of handles that a process can allocate. The method that I am allocating the text box in finishes successfully but I have a feeling that the underlying Win32 graphics context is not being cleaned up. The TextBox does not implement IDisposable. How can I make sure it cleans up any resources it has used?

I'm thinking that if it was on a xaml page when the page went down the internals of the Presentation Framework might do that clean up but where it is it is not happening.

If anyone is interested here is the stack trace:

[Win32Exception: The operation completed successfully]
    MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d):15
    MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks):479
    System.Windows.Threading.Dispatcher..ctor():136
    System.Windows.Threading.Dispatcher.get_CurrentDispatcher():14
    System.Windows.DependencyObject..ctor():0
    System.Windows.Media.Visual..ctor(ResourceType resourceType):11
    System.Windows.UIElement..ctor():0
    System.Windows.FrameworkElement..ctor():11
    System.Windows.Controls.Control..ctor():0
    System.Windows.Controls.Primitives.TextBoxBase..ctor():0
    System.Windows.Controls.TextBox..ctor():11

I have found some other people with similar issues here and here I'm theorising it may be related to this (although this is old). It seems to be that in most cases the Win32 graphics stuff is leaking or not being cleaned up.

Community
  • 1
  • 1
Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228
  • I have no idea what you're talking about. WPF UI elements don't implement IDisposable because they don't need to, and all your code has NOTHING to do with "graphics context" (whatever that means). And there's no such thing in WPF as a "maximum number of handles" (whatever that means too). You need a running `System.Windows.Threading.Dispatcher` instance if you expect this to work. For that you will have to `Dispatcher.Run()`. – Federico Berasategui Jul 29 '13 at 15:54
  • @HighCore it works when running on an StaTaskScheduler. The underlying graphics context I refer to is the Win32 methods that are used for drawing. We had the same issue in another program where we were creating too many wpf drawings. I have edited the question and added some links to others with similar problems. Sorry if my terminology was unclear. – Aran Mulholland Jul 29 '13 at 23:39
  • I'm sorry, I don't want to sound disrespectful, but you obviously have `no idea` what you're talking about. All those links are about (crappy useless dinosaur) winforms and NOT WPF. WPF does not have all those horrible limitations. and WPF does NOT use any Win32 stuff to "draw" anything. It's based on DirectX. and the WPF rendering is not tied to the Controls, as is the case in winforms, therefore your code has nothing to do with any rendering stuff. Also, the WPF UI elements do NOT use any GDI handles so all those handle limits are irrelevant in WPF. – Federico Berasategui Jul 30 '13 at 02:02
  • Your error is caused by the fact that you are not doing `Dispatcher.Run()`, which is required by WPF. – Federico Berasategui Jul 30 '13 at 02:04
  • @HighCore If WPF does not use Win32 to draw anything, why is it in the stack trace? Even if it is not drawing whatever it is creating doesn't seem to be getting cleaned up. It works for the first few thousand times, after that we run into issues. – Aran Mulholland Jul 30 '13 at 02:46
  • AranMulholland you should only create 1 instance of `System.Windows.Threading.Dispatcher` and reuse that thoughtout the entire lifetime of the application, regardless if web application or otherwise. Make sure you create a single `STAThread` and have that running in an infinite loop – Federico Berasategui Jul 30 '13 at 02:49
  • If the thread associated with the `Dispatcher` is terminated, then another `Dispatcher` will have to be created every time and you will run into these issues. – Federico Berasategui Jul 30 '13 at 02:51
  • There's nothing to "clean up" because the Win32 issue is a per-process issue, and you should never have that many `Dispatcher` instances in any give process. – Federico Berasategui Jul 30 '13 at 02:53
  • Yeah that makes sense, I think that is the crux of the issue. I'll try that out. Thanks. – Aran Mulholland Jul 30 '13 at 02:54

1 Answers1

0

Thanks to HighCores comments I am now creating the text box on a dispatcher thread and everything is working fine. For those who are interested there is a repository here which uses the WPF text box to do spell checks in this fashion.

Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228