【问题标题】:.NET Backgroundworker Object's Thread Priority.NET Backgroundworker 对象的线程优先级
【发布时间】:2009-02-07 20:10:54
【问题描述】:

我正在尝试在我正在开发的应用程序中使用 .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
...

backgroundworker 的 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 的双核笔记本电脑。

【问题讨论】:

    标签: .net multithreading backgroundworker


    【解决方案1】:

    只是补充一下 Jon 和 Marc 已经说过的话:

    后台线程没有较低的优先级。前台线程和后台线程之间的区别在于,一旦没有更多前台线程在运行,CLR 就会关闭进程。线程池线程是后台线程。

    您实际上可以设置线程池线程的优先级,但是由于您几乎无法控制哪个线程池线程将实际运行您的任务,因此不建议这样做。如果您需要特定优先级的线程,您应该使用 Thread 类型创建它们并根据需要设置实例的优先级。

    【讨论】:

    • 为什么我不能将所有回复都标记为有帮助?他们每个人都有一些有用的建议......!
    • 您只能选择一个答案,但您可以对所有您认为有帮助的答案进行投票。
    【解决方案2】:

    是的,您的方法有问题 - 当队列为空时,您基本上是在紧密循环。无论线程优先级如何,这都是个坏主意。

    为此使用后台工作器没有任何问题,但入队/出队实际上应该只使用生产者/消费者队列,当您尝试在没有准备好的情况下出队时阻塞。

    我有一个生产者/消费者队列in my threading tutorial 的示例实现 - 请参阅链接页面的大约一半。顺便说一句,您需要某种方式来告诉出队过程它已经完成。 (例如,将空引用或其他特殊值排入队列。)该代码是在泛型之前编写的,但应该很容易更新。

    【讨论】:

    • 在您的示例中,您期望队列中有 10 个项目,并且消费者线程在出列 10 个项目时终止。在我的例子中,项目在整个应用程序生命周期中被添加到队列中(大约每秒 10 个项目),所以 oWork 永远不应该终止。那么除了紧循环还能做什么呢?
    • @Soundar:唯一的区别是终止条件。正如我在答案中建议的那样,您可以使用特殊值(例如 null)来指示终止 - 或者永远不会终止。重要的是在没有条目时阻塞(而不是循环)。
    • 谢谢。在进一步阅读您的教程时,我现在知道我做错了什么。我应该使用 Monitor.sleep 而不是 thread.sleep (我想知道为什么我仍然需要它)。并且 monitor.wait 似乎确实在 DoWork 函数中工作。
    • 哎呀,我的意思是在上面的评论中写“使用 Monitor.Wait 而不是 Thread.sleep”。
    • 是的 - Monitor.Wait 是这里的关键点,尽管您不能只替换当前对 Thread.Sleep 的调用 - 您需要在锁定时调用它。
    【解决方案3】:

    它并没有声称是低优先级 - 背景意味着 a:不是 UI 线程,b:它不会让进程保持活动状态。实际上,它可能与ThreadPool 线程有关。

    如果您想要特定优先级的线程,请使用您自己的 Thread 对象 - 但我通常不建议这样做...

    另外 - “背景”并不意味着“空闲时”。即使在单核机器上,您也可能会看到两个线程都获得尽可能多的 rnutime(如果他们想要的话)。多核更是如此。

    【讨论】:

    • 问题是当后台线程调用 UploadAsync 时,它似乎阻塞/减慢了 UI 线程。我可以这样说,因为上传发生时调试语句会暂停。我怎样才能避免这种情况?
    • 是双核笔记本电脑,Win XP。
    【解决方案4】:

    您可能想查看此工作线程实现。它具有保护构造函数,用于指定线程的名称、线程的优先级以及线程是否为后台线程。

    http://devpinoy.org/blogs/jakelite/archive/2008/12/20/threading-patterns-the-worker-thread-pattern.aspx

    【讨论】:

    • 链接已损坏。
    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 2010-09-22
    相关资源
    最近更新 更多