利用BackgroundWorker的关于WinForms控件的GUI操作的跨线程调用?线程、控件、操作、BackgroundWorker

2023-09-03 04:32:15 作者:厌你

在我自己的经验与多线程的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!"));    
}
 
精彩推荐
图片推荐