windows窗体中多线程和后台工作线程的几个问题
Some questions on Multithreading and Background worker threads in windows form
我在使用c++的windows窗体GUI应用程序中遇到了使用多线程的需要。从我对这个主题的研究来看,似乎后台工作线程是我的目的。根据示例代码,我有
System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e)
{
BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
e->Result = SomeCPUHungryFunction( safe_cast<Int32>(e->Argument), worker, e );
}
然而,有几件事我需要弄清楚并弄清楚
- 后台工作线程会让我的多线程生活更容易吗?
- 为什么需要e->Result?
- 传入backgroundWorker1_DoWork函数的参数是什么? 形参safe_cast(e->Argument)的目的是什么?
- 我应该在我的CPUHungryFunction()做什么?
- 如果我的CPUHungryFunction()有一个无限循环的while循环怎么办?
- 我是否可以控制我的工作线程的处理器时间?
- 能否更具体地控制在设定周期内循环的次数?当我只需要每秒循环30次时,我不想让cpu每秒循环1000次。*是否有必要控制GUI的更新速度?
将后台工作线程使我的多线程生活更容易吗?
是的,非常喜欢。它可以帮助您处理无法从工作线程更新UI的事实。特别是ProgressChanged事件可以让你显示进度,而RunWorkerCompleted事件可以让你使用工作线程的结果来更新UI,而不必处理跨线程问题。
为什么我需要e->Result?
将您所做的工作的结果传递回UI线程。您可以在RunWorkerCompleted事件处理程序e->Result属性中获得该值。然后用结果更新UI。
传递给函数的参数是什么?
告诉工作线程该做什么,它是可选的。其他方面与传递参数给任何方法相同,只是更尴尬,因为你不能选择参数。你通常会从你的UI传递某种值,例如,如果你需要传递多个值,使用一个小的helper类。总是倾向于在工作线程中获取UI值,那是非常麻烦的。
当然是刻录CPU周期。或者通常做一些需要很长时间的事情,比如数据库查询。这不会消耗CPU周期,但需要太长时间才能允许UI线程在等待结果时死亡。粗略地说,当你需要做一些超过一秒钟的事情时,你应该在一个工作线程上执行它,而不是在UI线程上。我应该在我的CPUHungryFunction()做什么?
如果我的CPUHungryFunction()有一个无限循环的while循环怎么办?
那么你的工人永远不会完成,也永远不会产生结果。这可能有用,但并不常见。你通常不会使用BGW,只是一个常规的线程,它的IsBackground属性设置为true。
我可以控制我的工作线程得到的处理器时间吗?
你可以通过调用Thread.Sleep()来人为地减慢它的速度。这不是一件常见的事情,启动工作线程的目的是做工作。休眠的线程正在以非生产性的方式使用昂贵的资源。
能否更具体地控制在设定周期内循环的次数?当我只需要每秒循环30次时,我不想每秒循环1000次来耗尽cpu。
和上面一样,你必须睡觉。执行循环30次,然后休眠一秒钟。
有必要控制GUI更新的速率吗?
是的,这很重要。ReportProgress()可以是一个消防水带,每秒生成数千个UI更新。当UI线程无法跟上这个速度时,你很容易遇到问题。您将注意到,UI线程不再执行其常规任务,如绘制UI和响应输入。因为它必须不断处理另一个调用请求以运行ProgressChanged事件处理程序。副作用是UI看起来冻结,你已经得到了你试图用worker解决的确切问题。它实际上并没有冻结,它只是看起来那样,它仍然在运行事件处理程序。但是你的用户不会看到区别。
要记住的一件事是ReportProgress()只需要保持人眼满意。它不能看到每秒发生超过20次的更新。除此之外,它就变成了难以辨认的模糊。所以不要把时间浪费在无用的UI更新上。你也会自动避免消防水管的问题。调整更新速率是你必须编程的事情,它不是内置在BGW中。
我会一个问题一个问题地回答你
- 对
- DoWork是一个void方法(并且需要如此)。
DoWork
也执行了在与调用线程不同的线程中,所以你需要返回一些东西给调用线程的方法。e ->结果参数将传递给内部的RunWorkerCompleted
事件RunWorkerCompletedEventArgs
- sender参数是你可以使用的后台工作者本身为UI线程,
DoWorkEventArgs
最终引发事件包含从调用线程传递的参数(具有callRunWorkerAsync(Object)
) 无论你需要做什么。注意用户界面不能从DoWork线程访问的元素。通常,一个计算完成工作的百分比并更新UI(进度)bar或类似的东西)并调用ReportProgress进行通信UI线程。(需要有 - 没有无限期运行。你可以随时拔掉电源线。说真的,它只是另一个线程,操作系统会处理它当你的应用程序结束时,会破坏所有的东西。 不知道你是什么意思,但这可能是相关的到下一个问题
- 你可以使用线程。睡眠或线程。方法来释放一个循环后的CPU时间。睡觉的确切时间应该没问题根据您正在做的事情,当前的工作负载进行调整系统和处理器的原始速度
WorkerReportProgress
属性设置为真的)请参考MSDN文档中的BackgroundWorker和Thread类
- 工作线程在执行太快后永久休眠
- ZeroMQ 在使用 std::thread 创建工作线程时崩溃
- 工作线程一直在等待,condition_variable甚至调用了notify_all
- 使用 std::atomic 标志和 std::condition_variable 在工作线程上等待
- Qt-工作线程崩溃时将cv::Mat转换为QImage
- 无法将接口从主线程封送到工作线程
- 在 C++ 中扩展作业/工作线程多线程系统
- Qt C++ - 如何将数据从工作线程传递到主线程?
- 从线程池工作线程使用 GetQueuedCompletionStatus 的奇怪行为
- QtThread:I/O 队列的工作线程
- 将信号从工作线程类连接到控制器类 - QThreads
- Qt:工作线程和 GUI 事件之间的关系
- 将数据集几乎平均分配给工作线程
- 在为工作线程访问 lambda 中捕获的向量列表中的元素引用时,是否需要互斥锁?
- 如何将C++ dll 在 C# 窗口窗体应用程序下的工作线程中运行
- 在Qt中使用工作线程将数据写入文件的正确方法是什么?
- 在工作线程中使用 QT 主窗口
- C++,pthreads:如何从多个线程停止工作线程
- 同步主线程和工作线程
- 从工作线程更新QtCharts的正确方法