如何避免每种方法创建一个backgroundworker? [英] How to avoid creating a backgroundworker per method?

查看:145
本文介绍了如何避免每种方法创建一个backgroundworker?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我正试图围绕这个异步和后台工作人员的事情......

作为一个游乐场,我有一个搜索素数的WPF应用程序。 />


基础知识很简单。创建bgw(我的BackGroundWorker的简称),创建DoWork,RunWorkerCompleted,ProgressChanged委托。单击按钮后,将其运行为异步。完成工作后,更新GUI。大家都开心。这是主要代码:

Hi guys, I''m trying to wrap my mind around this asynchronous and background worker stuff ...
As a playground, i have a WPF application that searches for prime numbers.

Basics are easy. Create bgw (my short for BackGroundWorker), create DoWork, RunWorkerCompleted, ProgressChanged delegates. Once button clicked, run it async. once work is finished, update the GUI. Everybody happy. Here''s the main code:

private void btn_no_opt_go_Click(object sender, RoutedEventArgs e)
       {
           try {
               // Setting buttons states, showing progress bar, and setting the results label
               ...
               // Running our bgw worker.
               bgw.RunWorkerAsync(int.Parse(time_to_run.Text));
           } catch { ... }
       }

       // This does the work in an asynchronous way, calling the PrimeFinder class to do the heavy lifting.
       private void bgw_DoWork(object sender, DoWorkEventArgs e)
       {
           BackgroundWorker bgw = sender as BackgroundWorker;
           int arg = (int)e.Argument;

           // Start the time-consuming operation.
           PrimeFinder pf = new PrimeFinder(arg);
           e.Result = pf.No_Optimization(bgw);

           // Cancel code ....
       }

       // When method finishes, this runs
       private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
           // cancel / error / else + button initialization
       }

       /// Method is called every time bgw.ReportProgress is called which triggers ProgressChanged event.
       private void bgw_ProgressChanged(bject sender, System.ComponentModel.ProgressChangedEventArgs e)
       {
           prgs_no_opt.Value = e.ProgressPercentage;
       }

       // Cancel the operation (only selectable when it's running)
       private void btn_no_opt_cancel_Click(object sender, RoutedEventArgs e) {...}



还有一个名为Prime Finder的课程:


There''s also a class called Prime Finder which has:

// gets bgw so can call back with progress 
public PrimesResults No_Optimization(BackgroundWorker bgw)
{ 
   // hunt for primes, return an object when done
   ... 
}





GUI看起来像这样:



The GUI looks something like this:

No Optimization: [ progress bar ] [Go button] [Cancel button]
Results label: [holds the result / cancel / error code]





这很好用,一切都很开心。



现在我想改进并添加另一种更好的方法。所以,我正在添加GUI,现在看起来像:



This works nicely, and all are happy.

Now i want to improve and add another method that does things better. So, i''m adding to the GUI which now looks like:

No Optimization: [ progress bar ] [Go button] [Cancel button]
Results label: [holds the result / cancel / error code]

Some Optimization: [ progress bar ] [Go button] [Cancel button]
Results label: [holds the result / cancel / error code]





所以,我复制我的所有按钮和标签,粘贴它们,重命名它们使它们有意义,然后我复制粘贴上面的大部分代码。而不是bgw我有bgw_second,监听bgw_second_DoWork而不是bgw_DoWork,等等。



这看起来很愚蠢,多余,容易出错,浪费等等。

我怎么能有不同的按钮(每个按钮都有一个匹配的取消按钮),打电话和听不同的方法而不复制粘贴上面的东西?

请注意,不同的按钮调用不同的bgw,它使用该bgw调用另一个类,以便他们可以向正确的进度条报告进度,并取消正确的线程



另一个问题是:如果我使用1 bgw,并使用不同的参数调用它,因此它调用不同的方法,它会在1个线程上运行,还是会根据需要生成尽可能多的线程(如果我创建2或者更多不同的bgw和每个按钮调用其中一个)。

拥有一个多核CPU,在第一个方法上点击Go按钮,将在进程工作时最多一个核心(有意义) , 很多计算)。

点击第一个和第二个Go按钮,最多可以输出2个核心。有道理,因为我会接受它们系统跨越2 bgw,每个都得到他的核心,他们愉快地(或相当于不同的核心。看着任务经理,我看不到一个)核心被满载,但我看到负载是均匀共享的(给予或接受)


所以问题是我是否使用1 bgw,并将其作为参数(来自按钮)单击)要调用的方法,将单击这两个按钮导致使用2个线程(现在发生),或者只使用1个线程,共享2个调用之间的时间。



我想附上项目,但无法找到上传选项。



干杯:)



So, i copy all my buttons and labels, paste them, rename them around so they make sense, and then i copy paste most of the above code. instead of bgw i have bgw_second, with listeners for bgw_second_DoWork instead of bgw_DoWork, and so on.

This seems silly, redundant, prone to mistakes, wasteful, and so on.
How could I have different buttons (each button has a matching "cancel" button), call and listen to different methods without copy pasting the above things?
Notice that different buttons call different bgw, which call another class with that bgw so they can report progress to the correct progress bar, and cancel the correct thread

Another question is: if I use 1 bgw, and call it with different parameters so it calls different methods, will it run on 1 thread, or will it spawn as many threads as needed (which is the case if i create 2 or more different bgw and each button calls one of them).
Having a multiple core CPU, hitting the Go button on the first method, will max one core while the process is working (makes sense, lots of calculations).
Hitting the first and then the second Go buttons, will max out 2 cores. Makes sense, since i''ll take it them system spans 2 bgw, each gets his core, and they chunk away happily (or the equivalent to a core on different ones. looking at the task manager, i don''t see one core being fully loaded, but i see the load is evenly shared (give or take)

So the question is if i use 1 bgw, and give him as an argument (from the button clicked) the method to call, will clicking those 2 buttons result in 2 threads being used (as it happens now), or will only 1 thread be used, sharing the time between the 2 calls.

I wanted to attach the project, but cant find an upload option.

Cheers :)

推荐答案

也许,首先需要了解的是,这些方法与它们执行的线程完全无关。任何线程都可以调用任何方法,任何方法都可以在任何线程中调用。要真正理解它,你应该理解所有这些调用和返回模型的真正含义。它基于堆栈,每个线程都有自己的堆栈,以及上下文的其他元素。



第一个问题对我来说还不清楚。答案是肯定的,但是在项目开发中使用复制粘贴的想法甚至都没有引起我的注意,所以我根本不知道这是什么问题。如果你不得不复制一些东西,那么这些东西有很多共同之处。如果它有任何共同点,那么这个共同部分应该被抽象出来并在两种或更多种情况下使用。也许,我的第一段将向你解释,这里没有麻烦。另外,请看我对这个问题的评论。无论如何,不要重复自己(DRY)是最初的原则之一: http://en.wikipedia。 org / wiki / Don%27t_repeat_yourself [ ^ ]。



关于第二个问题:不,如果没有创建线程或从线程池中获取线程的显式代码,就不会创建线程。我甚至都不知道你是怎么回答这个问题的。可能你错过了一些非常基本的东西,但我无法理解是什么。



-SA
Perhaps, first thing you need to understand is that the methods are completely agnostic to the thread they are executed in. Any thread can call any methods, and any method can be called in any thread. To really understand it, you should understand how all this call-and-return model really words. It''s based on the stack, and each thread has its own stack, as well as other elements of the context.

First question remains unclear to me. The answer is yes, but the idea to use copy-paste in development of the project never even visit my head, so I simply don''t see what''s the problem. If you had to copy something, them this "something" had a lot in common. If it had anything in common at all, this common part should be abstracted out and used in two or more cases. Maybe, my first paragraph will explain to you, that there is no a hassle here. Also, please see my comments to the question. Anyway, "Don''t Repeat Yourself" (DRY) is one of the first principles: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself[^].

As to the second question: no, no threads are created without your explicit code which creates a thread or takes it from the thread pool. I don''t even know how you came to this question. Probably, you are missing something very basic, but I cannot understand what.

—SA


这篇关于如何避免每种方法创建一个backgroundworker?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆