How to access a WinForms control from another thread i.e. synchronize with the GUI thread?
Solution 1:
You can use this:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
TcpListener server = null;
while (true)
{
...
this.SynUI(()=>
{
if ( checkbox.Checked )
{
}
});
...
}
}).Start();
Or:
...
bool checked = false;
this.SynUI(()=> { checked = checkbox.Checked; });
...
Having:
static public class SyncUIHelper
{
static public Thread MainThread { get; private set; }
// Must be called from Program.Main
static public void Initialize()
{
MainThread = Thread.CurrentThread;
}
static public void SyncUI(this Control control, Action action, bool wait = true)
{
if ( control == null ) throw new ArgumentNullException(nameof(control));
if ( !Thread.CurrentThread.IsAlive ) throw new ThreadStateException();
Exception exception = null;
Semaphore semaphore = null;
Action processAction = () =>
{
try
{
action();
}
catch ( Exception ex )
{
exception = ex;
}
};
Action processActionWait = () =>
{
processAction();
semaphore?.Release();
};
if ( control.InvokeRequired && Thread.CurrentThread != MainThread )
{
if ( wait ) semaphore = new Semaphore(0, 1);
control.BeginInvoke(wait ? processActionWait : processAction);
semaphore?.WaitOne();
}
else
processAction();
if ( exception != null )
throw exception;
}
}
Adding in the Program.Main before the Application.Run:
SyncUIHelper.Initialize();
You can find on stack overflow various ways to synchronize threads with the UI thread like:
How do I update the GUI from another thread?
Update UI from Class (multithreaded)?
Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
There is BackgroundWorker too.