WPF - Случайное зависание с поведением файлового браузера - PullRequest
0 голосов
/ 18 декабря 2009

У меня есть прикрепленное поведение, определенное таким образом, ..

    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) + 0015 * WindowsBase.dll! System.Windows.Threading.Dispatcher.GetMessage (ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x48 байт WindowsBase.dll! System.Windows.Threading.Dispatcher.PushFrameImpl (System.Windows.Threading.DispatcherFrame frame = {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) + 0x26 байт PresentationFramework.dll! System.Windows.Application.Run () + 0x19 байт Debugatron.exe! Debugatron.App.Main () + 0x5e байт C # [Родной для управляемого перехода]
[Управляемый к нативному переходу]
mscorlib.dll! System.AppDomain.nExecuteAssembly (сборка System.Reflection.Assembly, строка [] 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, строка [] активацииCustomData) + 0x65 байт mscorlib.dll! System.Runtime.Hosting.ApplicationActivator.CreateInstance (System.ActivationContext активацииContext) + 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 executeContext, System.Threading.ContextCallback, состояние объекта) + 0x6f байт
mscorlib.dll! System.Threading.ThreadHelper.ThreadStart () + 0x44 байта

Так вот, я видел подобные вещи раньше, когда делал какие-то асинхронные вещи, но в тот момент ничего этого не происходило. Единственный живой поток - это пользовательский интерфейс! Кроме того, я всегда получаю последний отладочный оператор, когда он зависает.

Кто-нибудь может указать мне правильное направление? Это сводит меня с ума!

Ответы [ 2 ]

1 голос
/ 17 июня 2010

У меня есть очень простое приложение WPF, которое использует элемент управления WPF WebBrowser в приложении WPF. У меня точно такая же проблема. Элемент управления WPF WebBrowser (когда Google Планета Земля запущена с использованием JavaScript) останавливается примерно в 75% случаев, когда я изменяю размер окна по горизонтали. Я получаю тот же самый дамп стека, как указано выше. Когда я копирую / запускаю исполняемый файл на другом ПК (на котором установлена ​​XP SP3), он работает нормально и никогда не зависает. У меня также есть более сложное многопоточное приложение, которое также зависает с похожим дампом стека (также ожидающим сообщения внутри библиотеки Threading) на этом ПК, но не на другом ПК. Приложение управления WPF WebBrowser имеет ту же проблему, нацелено ли оно на .Net 3.5 или 4.0. Я использовал NETfx_Setupverifier для проверки правильности установки .net, но я все еще подозреваю, что есть проблема либо с .net, либо с какой-либо утилитой COM, которая вызывает нестабильное взаимодействие .NET-COM. Также я предполагаю, что мое приложение ожидает неуправляемого события / сообщения, которое никогда не приходит из-за проблемы с взаимодействием. Я также написал то же самое простое приложение, используя WinForms / WinForm WebBrowser Control, и это приложение никогда не зависает на одном компьютере.

Есть ли у кого-нибудь предложения о том, как отследить причину? Я думаю о том, чтобы полностью удалить / переустановить .NET Framework, даже если они были подтверждены правильно. Я даже не знаю, где искать аномалии на стороне COM.

1 голос
/ 18 декабря 2009

Здесь приводятся некоторые почти случайные факты и вопросы, которые могут вам помочь.

Прежде всего, я не смог воспроизвести вашу проблему. Неважно, сколько я пытался. Это всегда работало.

Трассировка стека также выглядит хорошо для меня: она постоянно обрабатывает сообщения. Что именно вас смущает? Удалось на родной переход?

В приложении WPF не может быть одного потока. Что вы видите в окне Threads в VS Debugger?

Когда я нажимаю кнопку break all, я вижу вызов функции ofd.ShowDialog () в трассировке стека основного потока, и один рабочий поток с именем .NET SystemEvents остается в WindowThreadProc (), ожидая объекта синхронизации. Что ты видишь?

Похоже, вы как-то зашли в тупик.

Попробуйте обернуть OpenFileBrowser() содержимое в try... catch{}. Есть ли ошибки?

...