.NET 后台工作者对象的线程优先级
我正在尝试在我正在开发的应用程序中使用 .NET Backgroundworker 对象。
互联网上的所有材料都说该对象在“后台”运行,但我无法确认该后台线程确实在“低优先级”模式下运行。 出现这个问题是因为在 Windows 中(我假设)后台任务可以在“正常”或“低于正常”或“低”优先级模式下运行。
在我的应用程序中,我尝试通过调用在 DoWork 函数中自己设置优先级 ……
Thread.CurrentThread.Priority=ThreadPriority.Lowest
但这
似乎没有什么效果。 后台工作者会忽略这个调用吗?
我想解释一下:
我的应用程序是一个互联网客户端,它从房间收集有关温度、湿度等的实时数据,并使用 system.net.webclient 上传到网页(不是网络服务)
。 UploadValuesAsync(...) 调用
我已经编写了应用程序,以便客户端 GUI 从腔室收集数据,给它们加上时间戳,然后将它们排队等待上传,如下所示
...
Synclock objlock
debug.print("Queueing reading...")
dataQ.Enque(reading)
End Synclock
...
后台工作程序的 Dowork 函数出队,然后像这样上传
..............................................
Do
if dataQ.count() <> 0 then
Synclock objlock
reading = dataQ.DeQue()
End Synclock
Dim client As New System.Net.WebClient
...put the reading in NameValueCollection and upload to server page
req = new NameValueCollection
...
...
client.UploadValuesAsync(uri, "POST", req)
endif
thread.sleep(1) 'without this line the CPU usage goes upto 100% and seems to slow other tasks!
Loop
当我运行程序时,
我发现每当调用 UploadValuesAsync 时打印出调试窗口停止。 我还添加了调试语句,以随时查看队列中有多少读数。 如果这个任务确实以低优先级运行,我预计队列计数会随着数据的获取而快速增加,然后仅在前台空闲且未获取数据时才减少。 但这种情况并非如此。 一旦将读数添加到队列中,它就会出列并上传。 所以队列计数总是要么 1 要么 0!
我的做法有什么问题吗? 我应该根本不使用后台工作对象吗?
顺便说一句,这是在运行 Windows XP 的双核笔记本电脑中。
I am trying to use the .NET Backgroundworker Object in an application I am developing.
All the material on the internet say that this object runs in the "background" but nowhere have I been able to confirm that this background thread indeed runs in a "low priority" mode. This question arises because in Windows (I assume) a background task can run in a 'normal' or 'below normal' or 'low' priority mode.
In my application, I tried to set the priority myself inside the DoWork function by calling
...
Thread.CurrentThread.Priority=ThreadPriority.Lowest
...
but this seems to have no effect. Does the backgroundworker ignore this call?
I would like to explain some more:
My application is an internet client that collects real-time data on temperature,humidity etc from a chamber and uploads to a web page (not a web service) using
system.net.webclient.UploadValuesAsync(...)
calls
I have written the application such that the client GUI collects the data from the chamber, time-stamps them and then queues them for upload like so
...
Synclock objlock
debug.print("Queueing reading...")
dataQ.Enque(reading)
End Synclock
...
The backgroundworker's Dowork function dequeues and then uploads like so...
..............
Do
if dataQ.count() <> 0 then
Synclock objlock
reading = dataQ.DeQue()
End Synclock
Dim client As New System.Net.WebClient
...put the reading in NameValueCollection and upload to server page
req = new NameValueCollection
...
...
client.UploadValuesAsync(uri, "POST", req)
endif
thread.sleep(1) 'without this line the CPU usage goes upto 100% and seems to slow other tasks!
Loop
................
When I run the program I find that whenever the UploadValuesAsync is called the print out the debug window stops. I had also added debug statements to see how many readings are in the queue at any time. It this task is truly run in a low priority, I expected to see the queue count increase rapidly as data is acquired and then decrease only when foreground is idle and data is not being acquired. But this is not the case. As soon as a reading is added to the queue it is dequeued and uploaded. So the queue count is always is either 1 or 0!
Is there something wrong in my approach? Should I not be using the background-worker object at all?
BTW, this is in a dual-core laptop running Windows XP.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只是补充 Jon 和 Marc 已经说过的话:
后台线程没有较低的优先级。 前台线程和后台线程之间的区别在于,一旦不再有前台线程运行,CLR 将关闭进程。 线程池线程是后台线程。
您实际上可以设置线程池线程的优先级,但由于您几乎无法控制哪个线程池线程将实际运行您的任务,因此不建议这样做。 如果您需要特定优先级的线程,您应该使用线程类型创建它们,并根据需要在实例上设置优先级。
Just to add to what Jon and Marc have already said:
Background threads do not have lower priority. The difference between foreground and background threads is that the CLR will shutdown the process once no more foreground threads are running. Thread pool threads are background threads.
You can actually set the priority of a thread pool thread, but as you have next to no control of which thread pool thread will actually run your task it is not advisable to do so. If you need threads of a specific priority you should create them using the Thread type and set the priority on the instance as desired.
是的,你的方法有问题 - 当队列为空时,你基本上是紧密循环的。 无论线程优先级如何,这都是一个坏主意。
为此使用后台工作人员没有任何问题,但是入队/出队实际上应该使用生产者/消费者队列,当您在没有任何准备好的情况下尝试出队时,该队列会阻塞。
我有一个生产者/消费者队列的示例实现在我的线程教程 - 查看链接页面下方大约一半的位置。 顺便说一句,您需要某种方法来告诉出队过程已完成。 (例如,将空引用或其他特殊值排入队列。)该代码是在泛型之前编写的,但应该很容易更新。
Yes, something is wrong with your approach - you're basically tight looping when the queue is empty. Whatever the thread priorities, that's a bad idea.
There's nothing wrong with using a background worker for this, but the enqueuing/dequeuing should really just use a producer/consumer queue which blocks when you try to dequeue when there's nothing ready.
I have an example implementation of a producer/consumer queue in my threading tutorial - see about half way down the linked page. You'll want some way to tell the dequeuing process that it's finished, by the way. (For example, enqueuing a null reference or other special value.) That code was written pre-generics, but it should be easy to update.
它并不声称自己是低优先级 - 后台意味着 a:不是 UI 线程,b:它不会使进程保持活动状态。 实际上,它可能与 ThreadPool 线程有关。
如果您想要一个特定优先级的线程,请使用您自己的 Thread 对象 - 但我通常不建议这样做......
此外 - “背景”并不意味着“空闲时”。 即使在单核机器上,您也可能会看到两个线程都获得同样多的 rnutime(如果它们想要的话)。 对于多核来说更是如此。
It doesn't claim to be low priority - background means a: not the UI thread, and b: it won't keep a process alive. In reality, it probably relates to
ThreadPool
threads.If you want a specific priority thread, then use your own
Thread
object - but I wouldn't recommend even this normally...Additionally - "background" doesn't mean "when idle". Even on a single core machine, you will probably see both threads get as much rnutime (if they want it). Even more so on multi-core.
您可能想看看这个工作线程的实现。 它具有受保护的构造函数,用于指定线程的名称、线程的优先级以及线程是否为后台线程。
http:// devpinoy.org/blogs/jakelite/archive/2008/12/20/threading-patterns-the-worker-thread-pattern.aspx
You might want to look at this worker thread implementation. It has protected constructors for specifying the name of the thread, the priority of the thread and whether or not the thread is a background thread.
http://devpinoy.org/blogs/jakelite/archive/2008/12/20/threading-patterns-the-worker-thread-pattern.aspx