yes visual messageboxbuttons icon critical c# winforms multithreading messages

c# - visual - Enviar o publicar un mensaje en un bucle de mensajes de Windows Forms



messagebox visual basic (3)

¿Realmente desea publicar un mensaje en el bucle de mensajes o simplemente desea actualizar algún control en su formulario, mostrar un cuadro de mensaje, etc.? Si es el primero, consulte la respuesta de @Noldorin. Si es lo último, entonces necesitas usar el método Control.Invoke () para reunir la llamada de tu hilo de "lectura" al hilo principal de la interfaz de usuario. Esto se debe a que los controles solo pueden actualizarse mediante el hilo en el que se crearon.

Esto es una cosa bastante estándar en .NET. Consulte estos artículos de MSDN para obtener los conceptos básicos:

Una vez que entienda cómo hacer esto, consulte el blog de Peter Duniho para saber cómo mejorar la técnica canónica.

Tengo un hilo que lee los mensajes de una tubería con nombre. Es una lectura de bloqueo, por lo que está en su propio hilo. Cuando este hilo lee un mensaje, quiero que notifique al bucle de mensajes de Windows Forms que se ejecuta en el hilo principal que hay un mensaje listo. ¿Cómo puedo hacer eso? En win32 haría un PostMessage, pero esa función no parece existir en .Net (o al menos no lo encontré).


En WinForms puedes lograr esto con Control.BeginInvoke . Un ejemplo:

public class SomethingReadyNotifier { private readonly Control synchronizer = new Control(); /// <summary> /// Event raised when something is ready. The event is always raised in the /// message loop of the thread where this object was created. /// </summary> public event EventHandler SomethingReady; protected void OnSomethingReady() { SomethingReady?.Invoke(this, EventArgs.Empty); } /// <summary> /// Causes the SomethingReady event to be raised on the message loop of the /// thread which created this object. /// </summary> /// <remarks> /// Can safely be called from any thread. Always returns immediately without /// waiting for the event to be handled. /// </remarks> public void NotifySomethingReady() { this.synchronizer.BeginInvoke(new Action(OnSomethingReady)); } }

Una variante más limpia de lo anterior que no depende de WinForms sería utilizar SynchronizationContext . Llame a SynchronizationContext.Current en su hilo principal, y luego pase esa referencia al constructor de la clase que se muestra a continuación.

public class SomethingReadyNotifier { private readonly SynchronizationContext synchronizationContext; /// <summary> /// Create a new <see cref="SomethingReadyNotifier"/> instance. /// </summary> /// <param name="synchronizationContext"> /// The synchronization context that will be used to raise /// <see cref="SomethingReady"/> events. /// </param> public SomethingReadyNotifier(SynchronizationContext synchronizationContext) { this.synchronizationContext = synchronizationContext; } /// <summary> /// Event raised when something is ready. The event is always raised /// by posting on the synchronization context provided to the constructor. /// </summary> public event EventHandler SomethingReady; private void OnSomethingReady() { SomethingReady?.Invoke(this, EventArgs.Empty); } /// <summary> /// Causes the SomethingReady event to be raised. /// </summary> /// <remarks> /// Can safely be called from any thread. Always returns immediately without /// waiting for the event to be handled. /// </remarks> public void NotifySomethingReady() { this.synchronizationContext.Post( state => OnSomethingReady(), state: null); } }


PostMessage (y también SendMessage ) son funciones de la API de Win32 y, por lo tanto, no están directamente asociados con .NET. Sin embargo, .NET tiene un buen soporte para interoperar con la API de Win32, utilizando llamadas P / Invoke.

Como parece que es nuevo en la programación de .NET de Win32, este artículo de MSDN Magazine proporciona una introducción sólida sobre el tema.

El excelente sitio web pinvoke.net detalla cómo usar muchas de estas funciones API de C # / VB.NET. Ver esta página para PostMessage específicamente.

La declaración estándar es la siguiente:

[DllImport("user32.dll", SetLastError = true)] static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

Pero como lo indica la página, es aconsejable envolver esta función para manejar los errores de Win32 correctamente:

void PostMessageSafe(HandleRef hWnd, uint msg, IntPtr wParam, IntPtr lParam) { bool returnValue = PostMessage(hWnd, msg, wParam, lParam); if(!returnValue) { // An error occured throw new Win32Exception(Marshal.GetLastWin32Error()); } }