0

我有一个这样定义的附加行为,..

    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");
                }
        }
    }
}

这是一个很好的简单附加行为,当您单击文本框时会弹出打开 OpenFileDialog 并在完成后将文件名放入框中。

它可能在 40% 的时间内工作,但其余时间整个应用程序都会挂起。此时的调用堆栈如下所示 -

[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(参考 System.Windows.Interop.MSG msg,System.IntPtr hwnd,int minMessage,int maxMessage)+ 0x48 字节 WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame 帧= {System.Windows.Threading.DispatcherFrame}) + 0x8b 字节 WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame 帧) + 0x49 字节
WindowsBase.dll!System.Windows.Threading。 Dispatcher.Run() + 0x4c 字节
PresentationFramework.dll!System.Windows.Application.RunDispatcher(对象忽略) + 0x1e 字节
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window 窗口) + 0x6f 字节 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]
[管理到本地转换]
mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly 程序集,string[] args) + 0x19 字节 mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e 字节 mscorlib.dll!System .Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 字节 mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 字节 mscorlib.dll!System.Runtime.Hosting。 ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa 字节 mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e 字节
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 字节
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象状态) + 0x66 字节
mscorlib.dll!System.Threading。 ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态) + 0x6f 字节
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 字节

现在,我以前在做一些异步事情时见过这种事情,但那时还没有发生。唯一活着的线程是 UI 线程!此外,当它挂起时,我总是得到最后一个调试语句。

谁能指出我正确的方向?这个快把我逼疯了!

4

2 回答 2

1

这里有一些几乎随机的事实和问题,可能会对您有所帮助。

首先,我无法重现您的问题。不管我多么努力。它总是有效的。

堆栈跟踪对我来说也不错:它不断处理消息循环。究竟是什么让你感到困惑?管理到本地过渡?

WPF 应用程序中不能有一个线程。您在 VS 调试器的“线程”窗口中看到了什么?

当我点击 break all 时,我在主线程堆栈跟踪中看到对 ofd.ShowDialog() 的调用,并且一个名为 .NET SystemEvents 的工作线程留在 WindowThreadProc() 中,等待同步对象。你看到了什么?

看起来你不知何故陷入了僵局。

尝试将OpenFileBrowser()内容包装到try... catch{}. 有没有错误?

于 2009-12-18T18:11:37.433 回答
1

我有一个非常简单的 WPF 应用程序,它在 WPF 应用程序中使用 WPF WebBrowser 控件。我有完全一样的问题。当我水平调整窗口大小时,WPF WebBrowser 控件(使用 JavaScript 启动的 Google 地球)冻结了大约 75% 的时间。我得到与上面列出的完全相同的堆栈转储。当我在另一台 PC(都运行 XP SP3)上复制/运行可执行文件时,它运行良好并且永远不会挂起。我还有一个更复杂的多线程应用程序,它在这台 PC 上也挂起类似的堆栈转储(也在线程库中等待消息),而不是另一台 PC。无论是针对 .Net 3.5 还是 4.0,WPF WebBrowser 控件应用程序都存在同样的问题。我使用 NETfx_Setupverifier 来验证 .net 安装是否正确,但我仍然怀疑任何一个 .net 都存在问题。net 或某些导致 .NET - COM 互操作不稳定的 COM 实用程序。我也猜测我的应用程序正在等待一些由于互操作问题而永远不会到达的非托管事件/消息。我还使用 WinForms/WinForm WebBrowser Control 编写了相同的简单应用程序,并且该应用程序永远不会挂在同一台 PC 上。

有人对如何追查原因有任何建议吗?我正在考虑完全卸载/重新安装 .NET 框架,即使它们已被验证正确。我什至不知道在哪里寻找 COM 端的异常。

于 2010-06-17T08:44:03.447 回答