C++ 如何在FLTK库中使用Fl::awake
我想使用Fl::awake(callback)函数在FLTK程序中从主循环调用函数。我从子线程调用Fl::awake,它返回1(success),但我的函数从未被调用。我在主线程的循环中调用Fl::wait()。有什么方法可以解决这个问题吗?下面的代码是一个相对简单的FLTK 1.3应用程序的示例,它使用C++ 如何在FLTK库中使用Fl::awake,c++,fltk,C++,Fltk,我想使用Fl::awake(callback)函数在FLTK程序中从主循环调用函数。我从子线程调用Fl::awake,它返回1(success),但我的函数从未被调用。我在主线程的循环中调用Fl::wait()。有什么方法可以解决这个问题吗?下面的代码是一个相对简单的FLTK 1.3应用程序的示例,它使用Fl::awake(回调)。代码来自FLTK的测试目录。只要获取源代码,您就会发现许多示例。您没有给我们您的代码,但我假设您没有在线程中调用Fl::lock(),以及稍后调用Fl::unlock
Fl::awake(回调)
。代码来自FLTK的测试目录。只要获取源代码,您就会发现许多示例。您没有给我们您的代码,但我假设您没有在线程中调用Fl::lock()
,以及稍后调用Fl::unlock()
。这很重要,因为您不应该访问该部分之外的小部件
包括
#如果已定义_PTHREAD | | |(WIN32)
#包括
#包括
#包括
#包括
#包括
#包括“threads.h”
#包括
#包括
Fl_螺纹底螺纹;
Fl_浏览器*browser1,*browser2;
Fl_值_输出*value1,*value2;
int start2=3;
无效幻数(无效*p)
{
Fl_值_输出*w=(Fl_值_输出*)p;
w->labelcolor(荧光灯红色);
w->重新绘制标签();
}
void*prime_func(void*p)
{
Fl_浏览器*浏览器=(Fl_浏览器*)p;
Fl_值_输出*值;
int n;
整数步;
char=0;
如果(浏览器==浏览器2){
n=起始点2;
start2+=2;
步骤=12;
值=值2;
}否则{
n=3;
步骤=2;
值=值1;
}
//非常简单的素数计算器!
//
//此函数末尾的返回值永远无法到达,因此
//将在某些编译器中生成警告,但是我们需要
//return语句或其他编译器会抱怨没有返回
//为了避免在所有编译器上出现警告,我们愚弄了聪明的编译器
//相信我们有机会通过测试达到目的
//n>=0,知道在逻辑上,n在这个上下文中永远不会是负的。
如果(;)的(n>=0){
int-pp;
int hn=(int)sqrt((double)n);
对于(pp=3;pp=hn){
chars[128];
sprintf(s,“%d”,n);
//在访问浏览器小部件之前获取锁。。。
Fl::lock();
浏览器->添加;
浏览器->底线(浏览器->尺寸());
如果(n>值->值())值->值(n);
n+=阶跃;
//释放锁。。。
Fl::unlock();
//向主线程发送消息,此时它将
//为我们的浏览器小部件处理任何挂起的重画
//我们在这里传递的消息没有任何用途,所以我们也可以
//只需传递空值。
Fl::清醒(p);
如果(n>10000&&!骄傲){
骄傲=1;
Fl::唤醒(幻数、值);
}
}否则{
//这是不必要的,因为“n”和“step”是局部变量,
//然而,似乎至少MacOS X存在一些线程问题
//这会导致(堆栈)变量的半随机损坏。
Fl::lock();
n+=阶跃;
Fl::unlock();
}
}
返回0升;
}
int main(int argc,字符**argv)
{
Fl_双_窗口*w=新的Fl_双_窗口(200200,“单线程”);
browser1=新的Fl_浏览器(0,0,200,175);
w->可调整大小(浏览器1);
value1=新的Fl_值_输出(10017520025,“最大质数:”);
w->end();
w->show(argc,argv);
w=新的Fl_双_窗(200200,“六螺纹”);
browser2=新的Fl_浏览器(0,0,200,175);
w->可调整大小(浏览器2);
value2=新的Fl_值_输出(10017520025,“最大质数:”);
w->end();
w->show();
browser1->add(“质数:”);
browser2->add(“质数:”);
//通过从主线程锁定来启用多线程支持
//thread.Fl::wait()和Fl::run()调用Fl::unlock()和
//Fl::lock()根据需要释放对子线程的控制
//当这样做是安全的。。。
Fl::lock();
//开始线程。。。
//在一个浏览器中显示一个线程
fl_create_thread(prime_thread、prime_func、browser1);
//在另一个浏览器中显示多个线程
fl_创建_线程(prime_线程、prime_函数、浏览器2);
fl_创建_线程(prime_线程、prime_函数、浏览器2);
fl_创建_线程(prime_线程、prime_函数、浏览器2);
fl_创建_线程(prime_线程、prime_函数、浏览器2);
fl_创建_线程(prime_线程、prime_函数、浏览器2);
fl_创建_线程(prime_线程、prime_函数、浏览器2);
Fl::run();
返回0;
}
#否则
#包括
int main(){
fl_警报(“对不起,此平台不支持线程化!”);
}
#endif//HAVE_PTHREAD | | WIN32
我实际上不调用lock和unlock,因为我不访问主线程之外的小部件。我只是用清醒作为一种信号机制。main中的lock调用解决了这个问题,感谢您为我指明了正确的方向。注意:这段代码允许“处理”线程在后台运行,同时让GUI仍然具有响应性,但此实现可以让处理线程被非响应GUI挂起。例如,如果调整窗口大小,并在调整大小时拖动鼠标,素数的计算将停止,直到停止创建GUI事件为止。调用Fl::awake()并不能避免这个问题,因为您仍然需要一个锁/解锁来让主线程注意到awake()事件。因此,如果你想让你的“处理”线程不受GUI的影响,你不能进行任何FLTK调用。稍微无关,但让我补充一下:在main函数中调用Fl::lock()
是非常重要的。我试图编写一个没有该调用的程序,但由于争用,该程序无法运行。
#if HAVE_PTHREAD || defined(WIN32)
# include <FL/Fl.H>
# include <FL/Fl_Double_Window.H>
# include <FL/Fl_Browser.H>
# include <FL/Fl_Value_Output.H>
# include <FL/fl_ask.H>
# include "threads.h"
# include <stdio.h>
# include <math.h>
Fl_Thread prime_thread;
Fl_Browser *browser1, *browser2;
Fl_Value_Output *value1, *value2;
int start2 = 3;
void magic_number_cb(void *p)
{
Fl_Value_Output *w = (Fl_Value_Output*)p;
w->labelcolor(FL_RED);
w->redraw_label();
}
void* prime_func(void* p)
{
Fl_Browser* browser = (Fl_Browser*) p;
Fl_Value_Output *value;
int n;
int step;
char proud = 0;
if (browser == browser2) {
n = start2;
start2 += 2;
step = 12;
value = value2;
} else {
n = 3;
step = 2;
value = value1;
}
// very simple prime number calculator !
//
// The return at the end of this function can never be reached and thus
// will generate a warning with some compilers, however we need to have
// a return statement or other compilers will complain there is no return
// statement. To avoid warnings on all compilers, we fool the smart ones
// into beleiving that there is a chance that we reach the end by testing
// n>=0, knowing that logically, n will never be negative in this context.
if (n>=0) for (;;) {
int pp;
int hn = (int)sqrt((double)n);
for (pp=3; pp<=hn; pp+=2) if ( n%pp == 0 ) break;
if (pp >= hn) {
char s[128];
sprintf(s, "%d", n);
// Obtain a lock before we access the browser widget...
Fl::lock();
browser->add(s);
browser->bottomline(browser->size());
if (n > value->value()) value->value(n);
n += step;
// Release the lock...
Fl::unlock();
// Send a message to the main thread, at which point it will
// process any pending redraws for our browser widget. The
// message we pass here isn't used for anything, so we could also
// just pass NULL.
Fl::awake(p);
if (n>10000 && !proud) {
proud = 1;
Fl::awake(magic_number_cb, value);
}
} else {
// This should not be necessary since "n" and "step" are local variables,
// however it appears that at least MacOS X has some threading issues
// that cause semi-random corruption of the (stack) variables.
Fl::lock();
n += step;
Fl::unlock();
}
}
return 0L;
}
int main(int argc, char **argv)
{
Fl_Double_Window* w = new Fl_Double_Window(200, 200, "Single Thread");
browser1 = new Fl_Browser(0, 0, 200, 175);
w->resizable(browser1);
value1 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:");
w->end();
w->show(argc, argv);
w = new Fl_Double_Window(200, 200, "Six Threads");
browser2 = new Fl_Browser(0, 0, 200, 175);
w->resizable(browser2);
value2 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:");
w->end();
w->show();
browser1->add("Prime numbers:");
browser2->add("Prime numbers:");
// Enable multi-thread support by locking from the main
// thread. Fl::wait() and Fl::run() call Fl::unlock() and
// Fl::lock() as needed to release control to the child threads
// when it is safe to do so...
Fl::lock();
// Start threads...
// One thread displaying in one browser
fl_create_thread(prime_thread, prime_func, browser1);
// Several threads displaying in another browser
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
Fl::run();
return 0;
}
#else
# include <FL/fl_ask.H>
int main() {
fl_alert("Sorry, threading not supported on this platform!");
}
#endif // HAVE_PTHREAD || WIN32