Reputation: 38162
Inspired by my own experience with multithreaded Winforms applications, as well as questions such as
I've come up with a very simple pattern, whose soundness I would like to verify.
Basically I'm creating (and running throughout the application's lifetime) a BGW whose sole purpose is the synchronization of invoke requests. Consider:
public MainForm()
{
InitializeComponent();
InitInvocationSyncWorker();
}
private void InitInvocationSyncWorker()
{
InvocationSync_Worker.RunWorkerAsync();
}
private void InvocationSync_Worker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(Timeout.Infinite);
}
void InvokeViaSyncWorker(Action guiAction)
{
InvocationSync_Worker.ReportProgress(0, guiAction);
}
private void InvocationSync_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (IsDisposed) return; //we're in the GUI thread now, so no race condition right?
var action = (Action) e.UserState;
action();
}
public void SomeMethodCalledFromAnyThread() //Sample usage
{
InvokeViaSyncWorker(() => MyTextBox.Text = "Hello from another thread!"));
}
Granted, it's not the most economical of approaches (keeping a thread alive like that), but if it works and I haven't missed anything, it sure is the simplest I've seen.
Feedback is highly appreciated !
Upvotes: 1
Views: 1249
Reputation: 22747
There's no need to open a thread just for that. Simply use SynchronizationContext
, like so:
private readonly SynchronizationContext _syncContext;
public MainForm()
{
InitializeComponent();
_syncContext = SynchronizationContext.Current;
}
void InvokeViaSyncContext(Action uiAction)
{
_syncContext.Post(o =>
{
if (IsHandleCreated && !IsDisposed) uiAction();
}, null);
}
public void SomeMethodCalledFromAnyThread() //Sample usage
{
InvokeViaSyncContext(() => MyTextBox.Text = "Hello from another thread!"));
}
Upvotes: 6