简体   繁体   English

这是使用后台工作者的正确方法吗?

[英]Is it a correct way of using background worker?

Saw this in some code but didn't make sense to me, So I was wondering if even it is a correct way of utilizing backgreound worker? 在某些代码中看到了这一点,但对我来说却毫无意义,所以我想知道这是否是使用backgreound工作者的正确方法?

it is used like this on Form_Load event: 它在Form_Load事件中像这样使用:

    BackgroundWorker asyncWorker = new BackgroundWorker();
    asyncWorker.DoWork += new DoWorkEventHandler(AsynchDoWork);
    asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(AsynchCompleted);
    asyncWorker.RunWorkerAsync();

   // a for each loop that can take some time to populate a combobx on the form

Also, is there a better alternative on achieving the same goal? 此外,在实现相同目标方面还有更好的选择吗? other than backgroundworker? 除了背景工作者?

If I understand correctly, what you are actually asking is if you should fill the values in your Combobox from a background thread or from the UI thread. 如果我理解正确,那么您实际上要问的是应该从后台线程还是从UI线程填充组合Combobox的值。

If the reason it takes a long time to populate the Combobox is because it takes a long time to actually retrieve the items - for example, if you are retrieving them from a database, then you probably should do this work in a BackgroundWorker , and then only add the retrieved items to the Combobox on the RunWorkerCompleted event. 如果填充组合Combobox需要花费很长时间的原因是实际检索这些条目需要花费很长时间-例如,如果要从数据库中检索它们,则可能应该在BackgroundWorker进行此工作,然后只有添加检索到的项目的ComboboxRunWorkerCompleted事件。

The RunWorkerCompleted event, while still running from a background thread, automatically calls Invoke under the hood for all access to UI elements, and therefore has no problem updating UI elements. RunWorkerCompleted事件虽然仍从后台线程运行,但它会在内部自动调用Invoke来访问UI元素,因此更新UI元素没有问题。

Of course, the long running lop has to be run inside the DoWork event, and not in the same code block as the call to RunWorkerAsync , as in your code example. 当然,长时间运行的垂耳有内部运行DoWork事件,而不是在同一个代码块中调用RunWorkerAsync ,在您的代码示例。

Conversely, if we are simply talking about a very large amount of readily available items, and the call to AddRange simply takes a lot of time because of the amount, you can not call this from a background thread, as winforms control can only be accessed from the UI thread. 相反,如果我们只是在谈论大量现成的项目,并且由于数量原因,对AddRange的调用仅花费大量时间,则不能从后台线程调用此项目,因为只能访问winforms控件从UI线程。

I would use the Task Parralell Library for this. 我将为此使用Task Parralell库。 A good into tutorial is Task Parallel Library: 1 of n . 一个很好的教程是Task Parallel Library:1 of n To update a combo box following the result of some background task you could do something like this 要根据某些后台任务的结果更新组合框,您可以执行以下操作

// Get UI scheduler. Use this to update ui thread in continuation.
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

// You can use TPL like this...
List<object> objList = new List<object>();
Task<object[]> task = Task.Factory.StartNew<object[]>(() =>
    {
        // Pull all your data into some object.
        object[] objArr = new object[] { "Some", "Stuff", "..." };
        return objArr;
    }, TaskCreationOptions.PreferFairness);

// Continuation firs after the antecedent task is completed.
task.ContinueWith(ant =>
    {
        // Get returned data set.
        object[] resultSet = (task.Result as object[]);

        // Check task status.
        switch (task.Status)
        {
            // Handle any exceptions to prevent UnobservedTaskException.             
            case TaskStatus.RanToCompletion:
                if (task.Result != null)
                {
                    // Update UI comboBox.
                }
                break;
            default:
                break;
        }
    }, CancellationToken.None, TaskContinuationOptions.None, uiScheduler);

Here the uiScheduler lets you update the ui thread from within the continuation delegate which fires when the antecedent task completes (either successfully or otherwise). 在这里uiScheduler允许您从延续委托中更新ui线程,该延续线程会在先验任务完成(成功或失败)时触发。

The continuation also acts as an exception handler in this case to catch any AggregateExceptions they may be thrown from the background thread. 在这种情况下,延续也充当异常处理程序,以捕获可能从后台线程引发的任何AggregateExceptions

I hope this helps. 我希望这有帮助。

I'm not sure about the scope, I would create the BackgroundWorker as a member of the class. 我不确定范围,我会创建BackgroundWorker作为类的成员。

The BackgroundWorker takes the work off of the UI thread and has methods that provide easy access to update progress. BackgroundWorker使UI线程的工作变得轻松,并具有可轻松访问更新进度的方法。

As for alternatives, it depends on what exactly your goals are. 至于替代方案,这取决于您的目标是什么。 If it is a small task that doesn't update the UI, then the System.Threading.ThreadPool is an option. 如果这是不更新UI的小任务,则可以选择System.Threading.ThreadPool。

To answer the question "Also, is there a better alternative on achieving the same goal? other than backgroundworker?". 要回答“除了背景工作者以外,在实现相同目标上还有更好的选择吗?”的问题。

No. This is the easiest way to handle long running blocking tasks for winforms. 否。这是处理winforms长时间运行的阻止任务的最简单方法。 There are other methods (BeginInvoke), but it is much easier to just use background worker. 还有其他方法(BeginInvoke),但是仅使用后台工作程序要容易得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM