【问题标题】:WinForm Multithreading. Use backgroundWorker or not?WinForm 多线程。是否使用 backgroundWorker?
【发布时间】:2012-07-15 01:54:39
【问题描述】:

我有一个简单的应用程序,可以触发一系列数据密集型任务。我对 WinForms 不是很有经验,我想知道在不锁定界面的情况下最好的方法。可以重复使用 backgroundWorker,还是有其他方法可以做到这一点?

谢谢

【问题讨论】:

  • 我会使用后台工作人员。
  • 如果您只需要一个其他线程,我会使用后台工作者,它们非常易于使用,并且已经完成了大部分艰苦的工作,为您提供不同工作阶段的直接事件完成。
  • 如果您需要该线程在完成密集工作后与 UI 元素交互,请使用 Backgroundworker。否则,如果您只是想要一些其他工作,例如从其他地方填充一些容器数据,这些数据在其他时间或事件中由主 UI 使用,则使用普通线程。
  • 好吧,他们用户可以启动各种不同的任务,然后通过 entityFramework 执行数据库操作。那么,当用户完成任务 A 后,后台工作人员是否可以再次用于任务 B?

标签: c# winforms multithreading


【解决方案1】:

您可以使用 BackgroundWorker 来满足此类要求。以下是updates a label status based on percentage task [long running] completion 的示例。此外,还有一个示例业务类,它设置了一些值,并通过ProgressChanged 处理程序将值设置回 UI。 DoWork 是您编写长时间运行的任务逻辑的地方。在 Winforms 应用程序上添加标签和 backgroundworker 组件后复制粘贴下面的代码并试一试。您可以调试各种处理程序[RunWorkerCompleted, ProgressChanged, DoWork] 并查看InitWorker 方法。请注意cancellation feature

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        private BackgroundWorker _worker;
        BusinessClass _biz = new BusinessClass();
        public Form3()
        {
            InitializeComponent();
            InitWorker();
        }

        private void InitWorker()
        {
            if (_worker != null)
            {
                _worker.Dispose();
            }

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _worker.DoWork += DoWork;
            _worker.RunWorkerCompleted += RunWorkerCompleted;
            _worker.ProgressChanged += ProgressChanged;
            _worker.RunWorkerAsync();
        }


        void DoWork(object sender, DoWorkEventArgs e)
        {
            int highestPercentageReached = 0;
            if (_worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                double i = 0.0d;
                int junk = 0;
                for (i = 0; i <= 199990000; i++)
                {
                    int result = _biz.MyFunction(junk);
                    junk++;

                    // Report progress as a percentage of the total task.
                    var percentComplete = (int)(i / 199990000 * 100);
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        // note I can pass the business class result also and display the same in the LABEL  
                        _worker.ReportProgress(percentComplete, result);
                        _worker.CancelAsync();
                    }
                }

            }
        }

        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Display some message to the user that task has been
                // cancelled
            }
            else if (e.Error != null)
            {
                // Do something with the error
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
        }
    }

    public class BusinessClass
    {
        public int MyFunction(int input)
        {
            return input+10;
        }
    }
}

【讨论】:

  • 感谢您的详细回复。我担心将我的“长时间运行的任务逻辑”添加到 DoWork 事件中。我有许多任务需要运行,将它们全部添加到一个 DoWork 事件中似乎不切实际。
【解决方案2】:

BackgroundWorker 是一个还包括通知同步的线程。例如,如果您想在扫描完成时更新您的 UI,常规的Thread 无法访问 UI 对象(只有 UI 线程可以这样做);因此,BackgroundWorker 提供了一个 Completed 事件处理程序,该处理程序在操作完成时在 UI 线程上运行。

更多信息请参见:Walkthrough: Multithreading with the BackgroundWorker Component(MSDN)

和一个简单的示例代码:

var worker = new System.ComponentModel.BackgroundWorker();
worker.DoWork += (sender,e) => Thread.Sleep(60000);
worker.RunWorkerCompleted += (sender,e) => MessageBox.Show("Hello there!");
worker.RunWorkerAsync();

【讨论】:

    【解决方案3】:

    后台工作人员将是一个不错的选择

    更多信息请看这里 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

    【讨论】:

      【解决方案4】:

      backgroundWorker可以使用。

      它的好处 - 它允许您更新进度条并与 UI 控件交互。 (WorkerReportsProgress)

      它还有一个取消机制。 (WorkerSupportsCancellation)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-01
        相关资源
        最近更新 更多