【问题标题】:BackgroundWorker thread to Update WinForms UIBackgroundWorker 线程更新 WinForms UI
【发布时间】:2016-04-13 07:11:05
【问题描述】:

我正在尝试从 BackgroundWorker 线程更新标签,该线程从 Form 之外的另一个类调用方法。所以我基本上想这样做:

MainForm.counterLabel.Text = Counter.ToString();

但标签是私有的。我已经研究过使用 BackgroundWorker 的 progressupdate 函数、调用等,但它们似乎不是我需要的。

这是我的更多代码:

主窗体:

clickThread.DoWork += (s, o) => { theClicker.Execute(speed); };
clickThread.RunWorkerAsync();

调用的类/方法:

public void Execute(int speed)
{
    while (running)
    {
       Thread.Sleep(speed);
       Mouse.DoMouseClick();
       Counter++;
       //Update UI here
    }
}

我认为我的代码有点过于复杂了:\ 并让自己陷入了困境。

【问题讨论】:

  • 如果标签是私有的,你会暴露一个方法或属性来设置它吗?
  • 所以要理解问题:对象“theClicker”无法访问MainForm的私有标签,对吗?解决此问题的一个非常糟糕的方法是将标签传递给“theClicker”的 Execute 方法。
  • BW 的基础很简单——不要DoWork 内部访问 UI。在DoWork 中做非 UI 的东西,在 ProgressChanged 中做 UI 的东西。
  • 之前的cmet一般。如果您的点击器的唯一“工作”是定期执行鼠标点击(UI 操作),那么 BW 根本不合适 - 简单的 Windows.Forms.Timer 就足够了。
  • 如果你不想使用 ProgressChanged,那么使用 BGW 是没有意义的。您可以只使用原始线程并在控件上调用 BeginInvoke。当然,更好的解决方案是使用 .NET 的 async/await 支持,这样您就可以运行异步任务以及从相同的方法更新 UI。

标签: c# multithreading winforms user-interface backgroundworker


【解决方案1】:

您应该使用ProgressChanged-Event 来更新 UI。 BackgroundWorker 的代码应该类似于:

internal static void RunWorker()
{
    int speed = 100;
    BackgroundWorker clickThread = new BackgroundWorker
    {
        WorkerReportsProgress = true
    };
    clickThread.DoWork += ClickThreadOnDoWork;
    clickThread.ProgressChanged += ClickThreadOnProgressChanged;
    clickThread.RunWorkerAsync(speed);

}

private static void ClickThreadOnProgressChanged(object sender, ProgressChangedEventArgs e)
{

    someLabel.Text = (string) e.UserState;

}

private static void ClickThreadOnDoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;
    int speed = (int) e.Argument;

    while (!worker.CancellationPending)
    {
        Thread.Sleep(speed);
        Mouse.DoMouseClick();
        Counter++;
        worker.ReportProgress(0, "newText-Parameter");
    }
}

}

【讨论】:

  • 谁否决了 BGW 的唯一正确用法?有人可能会争辩说,使用 Tasks 更好更容易,但这并不意味着使用专门构建的 ProgressChanged 事件是错误
  • 我想这个解决方案是最好的。我想我让自己接受了为 Execute 方法设置一个单独的类的想法。一旦我重构并且它起作用了,我就会接受这个答案。
  • 请注意“someLabel.Text = (string) e.UserState;”不起作用,因为该方法是静态的。
【解决方案2】:

尝试调用该方法。

例如:-

this.Invoke((Action)(() => Resources.xobjMF.Enabled = true));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多