0

我正在为多线程编程而苦苦挣扎......

我有一个通过 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 也会停止。直到 WaitForSingleObject(MutexMain) 失败后,DoHeartBeat 才会完成。

DoHeartBeat 是否在 MainThread 或 HeartBeatThread 的上下文中执行?它似乎在 MainThread 中执行。

我究竟做错了什么?有没有更好的办法?

谢谢,大卫

4

2 回答 2

0

首先,重新阅读有关心跳的规范。它是说必须每秒接收一次实际的心跳消息,还是必须每秒接收一些消息,并且如果没有其他消息在飞行中应该使用心跳?通道上数据的存在是通信通道处于活动状态的事实证据,因此不需要特定的心跳消息。

如果需要实际的心跳消息,并且每秒都需要,那么在上面的代码中应该只有一个互斥体,并且两个线程都需要共享它。编写的代码创建了两个单独的互斥锁,因此实际上都不会阻塞。您最终会在通道上发生冲突,并且在 CanBusApi 中会发生坏事。使 MainMutex 可见一个全局/类变量,并让两个线程都引用它。

于 2010-03-23T15:12:12.760 回答
0

我怀疑 CAN 总线 API 在幕后是单线程的。它可能正在将您的 DoHeartBeat() 请求从您的第二个线程编组回主线程。在这种情况下,由于您的主线程被阻塞,因此它无法成功。你可以通过两种方式解决这个问题:(1)向主线程发送一条消息,告诉它做心跳,而不是在第二个线程上做;或 (2) 在主线程上使用计时器而不是第二个线程来测量您的心跳。(我确实认为多线程对于这个特定问题来说太过分了。)

于 2010-03-23T15:10:52.990 回答