【问题标题】:Exploiting the BackGroundWorker for cross-thread invocation of GUI actions on Winforms controls?利用 BackGroundWorker 跨线程调用 Winforms 控件上的 GUI 操作?
【发布时间】:2011-05-10 13:42:13
【问题描述】:

灵感来自我自己使用多线程 Winforms 应用程序的经验,以及诸如

之类的问题

我想出了一个非常简单的模式,我想验证它的正确性。

基本上,我正在创建(并在应用程序的整个生命周期中运行)一个 BGW,其唯一目的是同步调用请求。考虑:

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!"));    
}

当然,这不是最经济的方法(像这样保持线程活跃),但如果它有效并且我没有错过任何东西,那肯定是我见过的最简单的方法。

非常感谢您的反馈!

【问题讨论】:

  • 我也这么认为 :) 希望这是一个好兆头,它还没有被证伪

标签: c# .net winforms synchronization backgroundworker


【解决方案1】:

没有必要为此打开一个线程。只需使用SynchronizationContext,就像这样:

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!"));    
}

【讨论】:

  • 谢谢!请注意,在这里使用PostBeginInvokeViaSyncContext 将是一个更合适的名称。我将创建 2 个重载,一个像上面那样(异步),一个使用 Send(同步)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
相关资源
最近更新 更多