2

私はgtkmmアプリケーションを持っていて、GUIをロックしないように、長時間実行されるタスクを別々のスレッドに入れようとしています。これが私のデザインのベースとなったチュートリアルです:

http://www.velvetcache.org/2008/09/30/gtkmmglibmm-thread-example

Glib :: Dispatcherシグナルを使用して、作業が完了したとき、または何かを更新する必要があるときにGUIスレッドに通知しますが、ワーカースレッドとGUIスレッドの間でデータを渡す方法がわかりません。これまで、ワーカーを作成するクラスへのポインターをワーカーに渡してから、クラスのパブリックメンバーを変更してきましたが、それを行うのが最も適切ではないことがわかりました。次に例を示します。

class Some_GUI_class
{
public:
    std::string thread_message;

private:
    Worker_class* worker;

    void start_worker()
    {
        if (worker != NULL) return;

        worker = new Worker_class(this);
        worker->sig_message.connect(sigc::mem_fun(*this, &Some_GUI_class::display_message_from_thread);
        worker.start();
    }        

    void display_message_from_thread()
    {
        some_label->set_text(thread_message);
    }
}

class Worker_class
{
public:
    Worker_class(Some_GUI_class* gui_class) : gui_class(gui_class)
    {}

    void start()
    {
        thread = Glib::Thread::create(sigc::mem_fun(*this, &Worker_class::run), true);
    }

    Glib::Dispather sig_message;

protected:
    Glib::Thread* thread;
    Glib::Mutex mutex;

    Some_GUI_class* gui_class;

    void run()
    {
        // ...
        gui_class->thread_message = "Message from a thread!";
        sig_message();                
    }

}

これは本質的には機能しますが、GUIスレッドが同時にthread_messageを変更したい場合は、問題が発生するのではないでしょうか。変数が単一のスレッドによってのみ変更されると確信している限り、このように行うのは安全ですか、それともより良い方法がありますか?

4

2 に答える 2

2

競合状態があります。GUIスレッドが変更されていない場合でも、thread_message別のスレッドが変更しているときにGUIスレッドがそれを読み取れるようにしても、長期的な幸福は得られません。これは、std :: string自体がそれにアクセスする複数のスレッドから保護されておらず、複数の内部フィールドがあるためです。1つのスレッドがその内部フィールドの1つを変更しているときに、別のスレッドがそれらを読み取っている場合、2番目の観点からは内部状態は一貫していません。

GUIクラスでミューテックスを使用して、別のスレッドによってアクセスされる可能性のある変数へのアクセスを保護できます。get / setルーチンでミューテックスをロックおよびロック解除し、他のすべてのアクセスにこれらのルーチンを使用して、一度に1つのスレッドのみが変数にアクセスまたは変更できるようにします。

于 2012-04-26T22:23:25.177 に答える
0

一般に、ミューテックスの使用は、目的の動作を実現するのに十分ではありません。同じワーカースレッド(または、ある場合は別のスレッド)が、最初のメッセージがまだメインスレッドによって処理されていないときに、別のメッセージを送信したい場合があります。そのため、この種のメッセージの損失を回避するには、ミューテックスに加えて、変数だけでなくメッセージキュー(std::deque<std::string>クラスのオブジェクトなど)を使用する必要があります。std::string Some_GUI_class::thread_message

于 2012-06-15T07:24:30.090 に答える