Обмен потоками - PullRequest
       36

Обмен потоками

0 голосов
/ 23 марта 2010

Я борюсь с многопоточным программированием ...

У меня есть приложение, которое общается с внешним устройством через CAN на USB модуль. У меня приложение нормально говорит по шине CAN, но существует требование, чтобы приложение передавало «сердцебиение» сообщение каждую секунду.

Звучит как идеальное время для использования тем, поэтому я создал тему который просыпается каждую секунду и посылает сердцебиение. Проблема я Имеет общий доступ к интерфейсу шины CAN. Сердцебиение должно быть отправлено только когда автобус простаивает. Как я могу поделиться ресурсом?

Вот псевдокод, показывающий, что у меня есть:

TMainThread
{
    Init:
        CanBusApi =new TCanBusApi;
        MutexMain =CreateMutex( "CanBusApiMutexName" );

        HeartbeatThread =new THeartbeatThread( CanBusApi );

    Execution:
        WaitForSingleObject( MutexMain );
        CanBusApi->DoSomething();
        ReleaseMutex( MutexMain );
}

THeartbeatThread( CanBusApi )
{
    Init:
        MutexHeart =CreateMutex( "CanBusApiMutexName" );

    Execution:
        Sleep( 1000 );
        WaitForSingleObject( MutexHeart );
        CanBusApi->DoHeartBeat();
        ReleaseMutex( MutexHeart );
}

Проблема, которую я вижу, заключается в том, что когда вызывается DoHeartBeat, он вызывает основной поток для блокировки во время ожидания MutexMain, как ожидалось, но DoHeartBeat также останавливается. DoHeartBeat не завершается до Тайм-аут WaitForSingleObject (MutexMain) завершился ошибкой.

DoHeartBeat выполняется в контексте MainThread или HeartBeatThread? Кажется, он выполняется в MainThread.

Что я делаю не так? Есть ли лучший способ?

Спасибо, David

Ответы [ 2 ]

0 голосов
/ 23 марта 2010

Во-первых, перечитайте спецификации о сердцебиении. Говорит ли он, что фактическое сообщение сердцебиения должно приниматься каждую секунду, или необходимо, чтобы какое-то сообщение принималось каждую секунду, и что сердцебиение должно использоваться, если другие сообщения не отправляются? Присутствие данных на канале является фактическим доказательством того, что канал связи активен, поэтому не требуется никакого конкретного сообщения пульса.

Если требуется фактическое сообщение пульса, и оно требуется каждую секунду, в приведенном выше коде должен быть только один мьютекс, и оба потока должны совместно использовать его. Написанный код создает два отдельных мьютекса, поэтому ни один из них не блокируется. Вы закончите столкновением на канале, и плохие вещи произойдут в CanBusApi. Сделайте MainMutex видимым как глобальную переменную / переменную класса, и оба потока ссылаются на нее.

0 голосов
/ 23 марта 2010

Я подозреваю, что API-интерфейс шины CAN является однопоточным под крышками. Это может быть маршалинг вашего запроса DoHeartBeat () из вашего второго потока обратно в основной поток. В этом случае у него не будет возможности добиться успеха, поскольку ваш основной поток заблокирован. Вы можете исправить это в основном двумя способами: (1) отправить сообщение в основной поток, сказав, что оно должно делать биение сердца, а не делать это во втором потоке; или (2) используйте таймер в главном потоке для вашего биения сердца вместо второго потока. (Я действительно думаю, что многопоточность излишня для этой конкретной проблемы.)

...