Can an asynchronous event fire synchronously in a form?

[VS 2010 Beta with .Net Framework 3.5]

I wrote a C # component for asynchronous socket control and raising events when receiving data. I set up a VB form to display message boxes when raising an event. I noticed that when a component fires an event synchronously, the message box blocks the component code and locks the form until the user closes the message. When it occurs asynchronously, it does not block the code or block the form.

What I want is a way to raise an event so that it does not block the code, but is called in the same thread as the form (so that it blocks the form until the user selects an option).

Could you help me? Thanks.

[component]

using System; using System.Threading; using System.ComponentModel; namespace mySpace { public delegate void SyncEventHandler(object sender, SyncEventArgs e); public delegate void AsyncEventHandler(object sender, AsyncEventArgs e); public class myClass { readonly object syncEventLock = new object(); readonly object asyncEventLock = new object(); SyncEventHandler syncEvent; AsyncEventHandler asyncEvent; private delegate void WorkerDelegate(string strParam, int intParam); public void DoWork(string strParam, int intParam) { OnSyncEvent(new SyncEventArgs()); AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null); WorkerDelegate delWorker = new WorkerDelegate(ClientWorker); IAsyncResult result = delWorker.BeginInvoke(strParam, intParam, null, null); } private void ClientWorker(string strParam, int intParam) { Thread.Sleep(2000); OnAsyncEvent(new AsyncEventArgs()); OnAsyncEvent(new AsyncEventArgs()); } public event SyncEventHandler SyncEvent { add { lock (syncEventLock) syncEvent += value; } remove { lock (syncEventLock) syncEvent -= value; } } public event AsyncEventHandler AsyncEvent { add { lock (asyncEventLock) asyncEvent += value; } remove { lock (asyncEventLock) asyncEvent -= value; } } protected void OnSyncEvent(SyncEventArgs e) { SyncEventHandler handler; lock (syncEventLock) handler = syncEvent; if (handler != null) handler(this, e, null, null); // Blocks and locks //if (handler != null) handler.BeginInvoke(this, e, null, null); // Neither blocks nor locks } protected void OnAsyncEvent(AsyncEventArgs e) { AsyncEventHandler handler; lock (asyncEventLock) handler = asyncEvent; //if (handler != null) handler(this, e, null, null); // Blocks and locks if (handler != null) handler.BeginInvoke(this, e, null, null); // Neither blocks nor locks } } } 

[the form]

 Imports mySpace Public Class Form1 Public WithEvents component As New mySpace.myClass() Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click component.DoWork("String", 1) End Sub Private Sub component_SyncEvent(ByVal sender As Object, ByVal e As pbxapi.SyncEventArgs) Handles component.SyncEvent MessageBox.Show("Synchronous event", "Raised:", MessageBoxButtons.OK) End Sub Private Sub component_AsyncEvent(ByVal sender As Object, ByVal e As pbxapi.AsyncEventArgs) Handles component.AsyncEvent MessageBox.Show("Asynchronous event", "Raised:", MessageBoxButtons.OK) End Sub End Class 
+4
source share
4 answers

You need to call the BeginInvoke method (only), which will run the delegate in the form user interface thread (thus blocking the form) without blocking the calling thread in order to wait for the call to complete.

If you do not have a link to the instance of the form, you can save SynchronizationContext.Current from the user interface stream, and then call Post on the SynchronizationContext instance, which will be equivalent.

+6
source

I recommend using SynchronizationContext.Post , passing the dialog code to the delegate. This will not block the code (another thread), but will execute the code of the dialog box in the user interface thread, so it will be blocked.

+1
source

Yes, you can use the Invoke() method on the form (or any control) to synchronize and execute any delegate in a synchronous path in the user interface thread.

0
source

If I understand you correctly, I think that you are approaching the problem in the wrong way.

I believe that you need to explicitly disable the controls on the form when you show the message box, and then turn them back on when the user closes the window.

Please clarify; Do you want the UI thread to display messages while the field is displayed? (for example, the form itself is repainted)

0
source

Source: https://habr.com/ru/post/1310013/


All Articles