2011-11-09 2 views
1

FLTKプログラムのメインループから関数を呼び出すためにFl :: awake(コールバック)関数を使用したいと考えています。私はFl :: awakeを子スレッドから呼び出すと、1(成功)を返しますが、私の関数は決して呼び出されません。私はFl :: wait()をメインスレッドのループで呼び出しています。これをトラブルシューティングする方法はありますか?FLTKライブラリのFl :: awakeの使用方法

答えて

0

以下のコードは、Fl::awake(callback)を使用する比較的単純なFLTK 1.3アプリケーションの例です。コードはFLTKのテストディレクトリにあります。ソースを取得するだけで、多くの例が見つかります。あなたは私たちにあなたのコードを教えてくれませんでしたが、Fl::lock()、そして後でFl::unlock()とあなたのスレッドに電話しなかったと思います。あなたはそのセクションの外ウィジェットにアクセスしてはならないので、それが不可欠である...

は、私はメインスレッドの外のウィジェットにアクセスしないので、私は実際にロックを呼び出してロックを解除していない

#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 
+0

が含まれます。私はシグナルメカニズムとして目を覚ましていました。私は正しい方向に向いてくれてありがとう、メインのロックコールはそれを修正するために働いた。 –

+0

注:このコードでは、「処理中の」スレッドをバックグラウンドで実行しながらGUIを応答させることができますが、この実装では応答しないGUIによって処理スレッドがハングアップする可能性があります。たとえば、ウィンドウのサイズを変更してサイズ変更中にマウスをドラッグするだけで、GUIイベントの作成を停止するまで素数の計算が停止します。主なスレッドにawake()イベントを知らせるためにロック/アンロックが必要なので、Fl :: awake()を呼び出しても問題は回避されません。したがって、あなたの "処理"スレッドをGUIから免除する場合は、FLTK呼び出しを行うことはできません。 – cape1232

+0

私はちょっと関係はありませんが、私に追加させてください:**メイン関数で 'Fl :: lock()'を呼び出すことは非常に重要です**私はその呼び出しをせずにプログラムを書くことを試みていました。競合。 – bcdan

関連する問題