Pregunta

Estoy creando un hilo que busca una ventana. Cuando encuentra la ventana, se anula su WindowProc, y las manijas WM_COMMAND y WM_CLOSE.

Este es el código que busca la ventana y subclases que:

public void DetectFileDialogProc()
{
   Window fileDialog = null;
   // try to find the dialog twice, with a delay of 500 ms each time
   for (int attempts = 0; fileDialog == null && attempts < 2; attempts++)
   {
      // FindDialogs enumerates all windows of class #32770 via an EnumWindowProc
      foreach (Window wnd in FindDialogs(500))
      {            
         IntPtr parent = NativeMethods.User32.GetParent(wnd.Handle);
         if (parent != IntPtr.Zero)
         {
            // we're looking for a dialog whose parent is a dialog as well
            Window parentWindow = new Window(parent);
            if (parentWindow.ClassName == NativeMethods.SystemWindowClasses.Dialog)
            {
               fileDialog = wnd;
               break;
            }
         }
      }
   }
   // if we found the dialog
   if (fileDialog != null)
   {
      OldWinProc = NativeMethods.User32.GetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC);
      NativeMethods.User32.SetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(new WindowProc(WndProc)).ToInt32());
   }
}

Y el WindowProc:

public IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
   lock (this)
   {
      if (!handled)
      {
         if (msg == NativeMethods.WM_COMMAND || msg == NativeMethods.WM_CLOSE)
         {       
            // adding to a list. i never access the window via the hwnd from this list, i just treat it as a number
            _addDescriptor(hWnd);
            handled = true;
         }
      }
   }
   return NativeMethods.User32.CallWindowProc(OldWinProc, hWnd, msg, wParam, lParam);
}        

Todo esto funciona bien en condiciones normales. Pero yo estoy viendo dos casos de mal comportamiento con el fin de maldad:

  1. Si no lo hago cerrar el diálogo dentro de un minuto más o menos, la aplicación se bloquea. ¿Esto es porque el hilo se está recolector de basura? Esto tipo de sentido esto, en lo que GC puede decir el hilo se hace? Si este es el caso, (y no sé que es), ¿cómo puedo hacer que la estancia hilo alrededor siempre y cuando el diálogo es de alrededor?

  2. Si yo inmediatamente cerrar el diálogo con el botón 'X' (WM_CLOSE) la aplicación se bloquea. Creo que su estrellarse en el WindowProc, pero no puedo conseguir un punto de interrupción en ese país. Recibo un AccessViolationException, La excepción dice "Intento de leer o escribir en la memoria protegida. Esto es a menudo una indicación de que otra memoria está dañada." Su condición de una carrera, pero de lo que no sé. Para su información, que había sido el restablecimiento del antiguo WindowProc vez Procesé los comandos, pero que estaba fallando incluso más a menudo!

¿Alguna idea sobre cómo puedo resolver estos problemas?

¿Fue útil?

Solución 2

Finalmente se le ocurrió una solución, atacando el problema desde un ángulo diferente. Yo era capaz de establecer un enlace de todo el sistema en código administrado utilizando SetWinEventHook, y la opción WINEVENT_OUTOFCONTEXT, que sorprendentemente tiene la propiedad: La función de devolución de llamada no está asignada al espacio de direcciones del proceso que genera el evento. Me trampa de la EVENT_SYSTEM_DIALOGSTART evento para recibir notificaciones cada vez que se crea un cuadro de diálogo, y cuando su EVENT_SYSTEM_DIALOGEND destruidos.

Otros consejos

Dos puntos de observación que puedo hacer ....

  • En su DetectFileDialogProc, que está comparando wnd a nulo, que es un tipo IntPtr sí? si es así, que el registro para la comparación debe ser if (wnd > IntPtr.Zero){ .... }
  • En su WndProc, está utilizando la variable this para la lock que es un mal que hay que hacer ... que debe hacer algo como esto private readonly object objLock = new object(); y dentro de su utilización WndProc este lock (objLock){....}

y ver si se soluciona el problema ....

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top