LinuxでDoEvents()同等機能

このQ&Aのポイント
  • Linux初心者です。2.6-18-at9 Debianで及ばずながらマルチスレッドのプログラムを書いています。
  • VBにはOSにコントロールを戻すDoEventsという機能があります。Windows/VC++ではこれと同等機能の関数を使っています。
  • どなたかの示唆によるもので内容はよく理解していませんが、Windows下ではこれで長年つかえてきました。Linux-gccで同等の関数は定義できるのでしょうか?。
回答を見る
  • ベストアンサー

LinuxでDoEvents()同等機能

Linux初心者です。 2.6-18-at9 Debianで及ばずながらマルチスレッドのプログラムを書いています。 VBにはOSにコントロールを戻すDoEventsという機能があります。 Windows/VC++ではこれと同等機能の関数を使っています: DWORD DoEvents(VOID) { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ if ( msg.message == WM_QUIT ){ return( msg.message ); } TranslateMessage( &msg ); DispatchMessage( &msg ); } return( 0 ); } どなたかの示唆によるもので内容はよく理解していませんが、Windows下ではこれで長年つかえてきました。 Linux-gccで同等の関数は定義できるのでしょうか?。

質問者が選んだベストアンサー

  • ベストアンサー
  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

PthreadsならPthreadクラスのsleepメソッドを用いてはどうでしょう。 http://www5a.biglobe.ne.jp/~mick/contents/program/pthread.html

gammodler
質問者

お礼

nora1962様 回答ありがとうございます。 PCからのデータ(data)を受信専用スレッドで受信、メインスレッドで data = 0; while (!data) sleep(1); printf(data %x\n, data); によりPCからのデータを取得できました。 sleep(1);は特に準備不要で使えました。 VC++におけるSleepでは同じことはできず、先に挙げたDoEvents()を使わざるを得なかったと記憶しています。 ありがとうございました。

その他の回答 (1)

  • sygh
  • ベストアンサー率76% (42/55)
回答No.2

WindowsのDoEventsは、GUIプログラムにおいて、メッセージ ループを持つメイン スレッド(UIスレッド)上で実行するべき処理であって、サブ スレッド(ワーカー スレッド)から呼び出してよいものではありません。 DoEventsは主にシングル スレッドのGUIプログラムにおいて、長時間かかる処理を実行している最中に、ユーザーによる中断指示の検出をする場合などに使われます。 マルチ スレッド プログラムにおいては、そもそもメイン スレッドでは長時間かかる処理を行なわないのが原則です。サブ スレッドとの通信や同期は、メッセージ キューやイベントなどの同期オブジェクト、スレッド間共有メモリなどを介して行ないます。 DebianのネイティブAPIは分かりませんが、Qtの場合、QCoreApplication::processEvents()がDoEventsに相当します。 http://qt.nokia.com/downloads-jp/ 下記はQtのサンプル コードです。 // 宣言ファイル。 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; bool isStopped; private slots: void on_btnStop_clicked(); void on_btnStart_clicked(); }; #endif // WIDGET_H // 実装ファイル。 #include "widget.h" #include "ui_widget.h" #include <qthread.h> class ThreadSleeper : public QThread { public: static void sleep(unsigned long secs) { QThread::currentThread()->sleep(secs); } static void msleep(unsigned long msecs) { QThread::currentThread()->msleep(msecs); } static void usleep(unsigned long usecs) { QThread::currentThread()->usleep(usecs); } }; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget), isStopped() { ui->setupUi(this); ui->progressBar->setValue(0); } Widget::~Widget() { delete ui; } void Widget::on_btnStart_clicked() { ui->btnStart->setEnabled(false); this->isStopped = false; ui->progressBar->setValue(0); do { for (int i = 0; i < 10; ++i) { ThreadSleeper::msleep(100); qApp->processEvents(); } ui->progressBar->setValue(ui->progressBar->value() + 10); } while (ui->progressBar->value() < ui->progressBar->maximum() && !this->isStopped); ui->btnStart->setEnabled(true); } void Widget::on_btnStop_clicked() { this->isStopped = true; }

gammodler
質問者

お礼

svgh様 回答ありがとうございます。 DoEventsの内容を理解せず、やみくもに使っていました。 当面の課題はsleep(1)で済み、これで先に進むことにしましたが、提示していただいたコードを解釈、DebianのAPIを調べてトレースしてみます。 勉強になりました。ありがとうございました。

関連するQ&A

  • PeekMessageについて

    確認したいのですが、 MSG msg; while(TRUE) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) { return (int) msg.wParam; } TranslateMessage(&msg); DispatchMessage(&msg); } else { } } このPeekMessageというものですがキューに溜めているということでいいのでしょうか。 後、 MSG msg; while(TRUE) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(!GetMessage(&msg,NULL,0,0)) { return (int) msg.wParam; } if(msg.message==WM_QUIT) { return (int) msg.wParam; } TranslateMessage(&msg); DispatchMessage(&msg); } else { } } の if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(!GetMessage(&msg,NULL,0,0)) { return (int) msg.wParam; } はキューから出してGetMessageは待機してるということでいいのでしょか? if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { if(!GetMessage(&msg,NULL,0,0)) { return (int) msg.wParam; } これはキューの中は出さないで、GetMessageでPeekMessageからのキューを出しているということでいいのでしょか?

  • メッセージループについて

    while(true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) break; DispatchMessage(&msg); if(!GetMessage(&msg,NULL,0,0)) { } } else { } これはpeekMessageがメッセージを取り出してメッセージがあったら if(msg.message==WM_QUIT) break; DispatchMessage(&msg); if(!GetMessage(&msg,NULL,0,0)) を実行して、GetMessage()で待機してもし、メッセージがWM_QUITならGetMessageにWM_QUITのメッセージを渡してメッセージが消えてPeekMessageはメッセージキューがないため、0を返し永遠にelseを繰り返すという認識でよろしいのですか? あと、while(true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(!GetMessage(&msg,NULL,0,0)) { } if(msg.message==WM_QUIT) break; DispatchMessage(&msg); } else { } if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))がWM_QUITのメッセージで そしてメッセージが消えてGetMessageで待機状態になるということでよろしいのでしょうか?ご教授お願いします。

  • メッセージループ

    while(true) { if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { if(msg.message==WM_QUIT) break; DispatchMessage(&msg); if(!GetMessage(&msg,NULL,0,0)) { return (int)msg.wParam; } } } else { } このソースで実行して消したら終了しませんでした。 なぜ終了できなかったのでしょうか?

  • Sleep(1)が1msでもどってこない。

    Sleep(1)が1msでもどってこない。 ゲームのループ処理を作っていまして、 空いている時間をシステムに返すためにSleep(1)を呼んで いるのですが、 while( msg.message != WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { //ゲーム的な処理 //時間があまればSleep() } } といった定番なことをしているのですが、 30FPSで固定されません。 調べてみるとSleep(1)が2msくらいして戻ってきています。 なにかよいアイディアを持っている方がいらっしゃいましたら教えてください。 よろしくお願いします。

  • 質問なのですが・・・

    while(true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) break; DispatchMessage(&msg); } else { if(FAILED(Render(g_pD3DDevice))) DestroyWindow(hWindow); } } でRenderが通らないのですがどうしたら通るようになるのでしょうか。

  • APIのメッセージループの流れとTranslateMessage

    while(GetMessage(&msg, NULL, 0, 0) > 0){ TranslateMessage(&msg); DispatchMessage(&msg); } もしも「a」が押されたときは、 GetMessageで受け取って TranslateMessageでWM_CHARに変換され DispatchMessageでWM_CHARとしてのメッセージが送られる という流れになるはずです。 けど、実際には一度プロシージャにWM_KEYDOWNが送られます。 TranslateMessageが先にメッセージを変換してるので、WM_KEYDOWNが送られることはありえないと思うのですが、なぜでしょうか。 何か重大な思い違いをしているのでしょうか・・?

  • FPS制御について

    今DirectDrawを使ったプログラムを組んでいて、そのプロジェクト内でFPSの制御関数(図1)を作りました。その関数は引数を1つ持っていて、その引数に渡した値がそのままフレームレートになるはずなのですが、実際は引数に指定した値よりもフレームレートが落ちています。   図1 FpsControl(60); ↑           1/60フレームレート FPS制御をしていない時にFPSを計ったときには500~600fps は出ていましたので処理自体が遅いわけではないと思います。 FPS制御関数はメッセージループ部分(図2)で使っています。   図2 while(TRUE){ //メッセージがある場合 if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); }else{ //メッセージが無い場合 if(FpsControl(60))Game_Main();//プログラ ムのメイン部分 ↑    ↑ }        ↑                   ↑                **ここで使ってます** 関数の内部処理は何度も確認したので間違ってないと思います。 ずっとこのバグについて考えいろいろ試しましたが、 結局原因はわからずここに助けを求めに来ました。 お願いします。

  • FPSについて

    一つ質問なのですが、FPSの計測したいのですが、以下のソースでやるとFPSが57になってしまうのですが。 どうしたらFPSを60にすることが出来るのでしょうか? 多分ここら辺だろうなというところを載せます。 void FPSCount(void){ static DWORD before_time = timeGetTime(); // 以前の時間 DWORD now_time = timeGetTime(); // 現在の時間 static DWORD fps_ctr = 0; TCHAR buff[80]; // 文字列表示用バッファ if(now_time - before_time >= 1000){ // 初期化 before_time = now_time; *fps = fps_ctr;     wsprintf(buff,_T("%d\n"),fps_ctr);     OutputDebugString(buff);     fps_ctr = 0; } fps_ctr++; } // エントリポイント int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )      ・      ・      ・ // メッセージループ while(true) { if (PeekMessage(&msg, NULL, 0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { // 同期処理 if (timeGetTime() - dwStart >= 1000.0/FPS) { FPSCount(); // 時間更新 dwStart = timeGetTime(); fps=0; // 描画処理 Draw(); } } Sleep(1); } timeEndPeriod(1); // 終了処理 Cleanup(); // 戻り値を返します。 return (int)msg.wParam; } } です。 環境はVC+2005です。

  • PeekMessage()について

    Windowsフォームアプリケーションです。 ループさせたいイベント(button1)中に、button2のイベントを行いたいのでPeekMessage()を使って以下のようにしました。 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { while(1){ PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); TranslateMessage(&msg); DispatchMessage(&msg); // ループさせたいイベント ・・・・・・・・・・・・・・・・・・・・ } } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {    ・・・・・・・・・・・・・・・・・・・・ } アプリケーション起動後、button1をクリックし、後にbutton2をクリックしようとすると代わりにbutton1がクリックされてしまいます。 PeekMessage()の使い方が間違っているのでしょうか。

  • ウィンドウ内でマウスが乗ると更新が止まります・・

    ウィンドウプロシージャ周りを触っているのですが、  ・ウィンドウにマウスが乗っていつつ、マウスが動いている時  ・キーボードーを押した瞬間 にメインループに処理が回らず 全体の処理が止まってしまいます。 上の問題を解決するには、どうすれば良いでしょうか? ※以下コード ---------------------------------------------- while(TRUE) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { // 処理メッセージが無いとき WINDOWPLACEMENT wndpl; GetWindowPlacement(hWnd, &wndpl); if((wndpl.showCmd != SW_HIDE) && (wndpl.showCmd != SW_MINIMIZE) && (wndpl.showCmd != SW_SHOWMINIMIZED) && (wndpl.showCmd != SW_SHOWMINNOACTIVE)) { ... ゲームのような、常時更新が必要なループ処理 ... } } Sleep(1); // 最小化等でフリーズしないため } ---------------------------------------------- //以下メッセージ処理側の一部 case WM_KEYDOWN: if (wParam == VK_ESCAPE) { PostQuitMessage(0); } break; case WM_MOUSEMOVE: return DefWindowProc(hWnd, msg, wParam, lParam); default: return DefWindowProc(hWnd, msg, wParam, lParam); ---------------------------------------------- また、ゲームなどのリアルタイム更新に向いた ウィンドウプロシージャの作り方などの説明サイト等ご存知でしたら そちらも教えて頂けると幸いです。

専門家に質問してみよう