views:

298

answers:

2

Hi,

I have an attached behavior defined thusly,..

    public static class FileBrowserBehaviour
{


 public static bool GetBrowsesOnClick(DependencyObject obj)
 {
  return (bool)obj.GetValue(BrowsesOnClickProperty);
 }

 public static void SetBrowsesOnClick(DependencyObject obj, bool value)
 {
  obj.SetValue(BrowsesOnClickProperty, value);
 }

 // Using a DependencyProperty as the backing store for BrowsesOnClick.  This enables animation, styling, binding, etc...
 public static readonly DependencyProperty BrowsesOnClickProperty =
  DependencyProperty.RegisterAttached("BrowsesOnClick", typeof(bool), typeof(FileBrowserBehaviour), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(BrowsesOnClickChanged)));


 public static void BrowsesOnClickChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
 {
  FrameworkElement fe = obj as FrameworkElement;

  if ((bool)args.NewValue)
  {
   fe.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(OpenFileBrowser);
  }
  else
  {
   fe.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(OpenFileBrowser);
  }
 }

 static void OpenFileBrowser(object sender, MouseButtonEventArgs e)
 {
  var tb = sender as TextBox;
  if (tb.Text.Length < 1 || tb.Text=="Click to browse..")
  {
   OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "Executables | *.exe";
    if (ofd.ShowDialog() == true)
    {
     Debug.WriteLine("Setting textbox text-" + ofd.FileName);
     tb.Text = ofd.FileName;
     Debug.WriteLine("Set textbox text");
    }
  }
 }
}

It's a nice simple attached behavior which pops open an OpenFileDialog when you click on a textbox and puts the filename in the box when you're done.

It works maybe 40% of the time but the rest of the time the whole app hangs. The call stack at this point looks like this -

[Managed to Native Transition]

WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + 0x15 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x48 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) + 0x8b bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x1e bytes PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes PresentationFramework.dll!System.Windows.Application.Run() + 0x19 bytes Debugatron.exe!Debugatron.App.Main() + 0x5e bytes C# [Native to Managed Transition] [Managed to Native Transition] mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly assembly, string[] args) + 0x19 bytes mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e bytes mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 bytes mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 bytes mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa bytes mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e bytes Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes

Now, I've seen this kind of thing before when doing some asynchronous stuff but there's none of that going on at that point. The only thread alive is the UI thread! Also, I always get that last debug statement when it does hang.

Can anyone point me in the right direction? This one's driving me crazy!

+1  A: 

Hi Stimul8d,

Here goes some almost random facts and questions, that might help you.

First of all, I couldn't reproduce your problem. No matter how much I tried. It always worked.

Stack trace also looks good for me: it keeps processing messages loop. What exactly confuses you? Managed to native transition?

You can't have one thread in WPF application. What do you see in the Threads window in VS Debugger?

When I hit break all I see the call to ofd.ShowDialog() in the main thread stack trace, and one worker thread named .NET SystemEvents stays in WindowThreadProc(), waiting on a sync object. What do you see?

It looks like you got into deadlock somehow.

Try wrap OpenFileBrowser() contents into try... catch{}. Are there any errors?

Anvaka
Tought that might be the case. You'll have to forgive my ignorance on the threading. Unfortunately, I'm not working in VS since I've only got VS2005 so I'm using express edition (I could use VS i guess but I think you lose some IDE benefits that way).As far as the message loop is concerned, I'm reasonably okay with most of what i see, it's just the app hanging which makes me think that my app is waiting on some unmanaged event.It's been a while since I've done any unmanaged stuff though so I'm sometimes a little rusty.Wrapping in a try catch seems like a good plan though. thanks
Stimul8d
+1  A: 

I have a very simple WPF application that uses the WPF WebBrowser control in a WPF application. I have exactly the same problem. The WPF WebBrowser control (with Google Earth launched using JavaScript) freezes about 75% of the time when I resize the window horizontally. I get the exact same stack dump as listed above. When I copy/run the executable on a different PC (all running XP SP3) it runs fine and never hangs. I also have a more complex app that is multi-threaded which also hangs with a similar stack dump (also waiting on a message inside the Threading library) on this PC but not another PC. The WPF WebBrowser control app has the same problem whether it is targeted for .Net 3.5 or 4.0. I used NETfx_Setupverifier to verify the .net installations are correct, but I still suspect there is an issue with either .net or some COM utility that is causing the .NET - COM interop to be unstable. It is also my guess that my app is waiting on some unmanaged event/message that never arrives because of a problem with the interop. I also wrote the same simple app using WinForms/WinForm WebBrowser Control and that app never hangs on the same PC.

Does anyone have any suggestions on how to track down the cause? I'm thinking about completely uninstalling/reinstalling the .NET frameworks even though they were verified correct. I don't even know where to look for anomalies on the COM side.

chetto
I'm not going completely insane then?!?!
Stimul8d
I have tried both the very simple WPF WebBroserCtrl app and the 2nd app with a background thread on more systems (all XP SP3). On 3 single processor/core systems, they always run and never hang. On 2 multi-core/hyperthreaded CPU systems both programs hang at the exact same place mentioned above. I expect the simple WPF WebBrowserCtrl is multithreaded inside the .net code making it a threadding issue in both cases. Is it possible that there is a .net threading issue with multi-core CPUs?
chetto
I also reverted both programs from .Net 4.0 to .Net 3.5 in case there there is a problem with .Net 4.0 under XP (The minimum XP configuration supported by .Net 4.0 is XP SP3.), but it does not appear to have made any difference.
chetto
I found to the problem in my case. I accidentally used a WinForms File Selection dialog box inside WPF which appears to not be thread-safe. I replaced System.Windows.Forms.OpenFileDialog class with Microsoft.Win32.OpenFileDialog class which solved the problem. Finding this problem was more difficult because the the coding error was far removed from the point of the crash, and VS C# Express leaves the programmer blind as to the threading; not even a list of threads.
chetto