在我自己的经验与多线程的WinForms应用程序,以及问题的启发,如
Inspired by my own experience with multithreaded Winforms applications, as well as questions such as
Avoiding调用/的BeginInvoke的跨线程的WinForm事件处理的困境? Avoid调用调用当控制设置 Avoiding the woes of Invoke/BeginInvoke in cross-thread WinForm event handling? Avoid calling Invoke when the control is disposed我想出了一个很简单的图案,其合理性,我想核实。
I've come up with a very simple pattern, whose soundness I would like to verify.
基本上我创建(和整个应用程序的生命周期中运行)一个BGW,其唯一目的是调用请求的同步。试想一下:
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.
反馈强烈AP preciated!
Feedback is highly appreciated !
有没有需要打开一个线程就是为了这一点。只需使用的SynchronizationContext
,像这样:
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 (!IsDisposed) uiAction();
}, null);
}
public void SomeMethodCalledFromAnyThread() //Sample usage
{
InvokeViaSyncContext(() => MyTextBox.Text = "Hello from another thread!"));
}