【发布时间】:2013-08-15 01:04:52
【问题描述】:
我正在重写一个有很多问题的 MFC 应用程序。主要问题是不稳定。
它是一个通过 USB 与外部模块通信的 GUI 应用程序。因此,它使用计时器每 n 毫秒运行一次通信堆栈。然而,定时器回调中不允许系统调用,因此程序不稳定,崩溃和挂起很多。
所以我必须重写应用程序以在后台线程中运行通信堆栈。 这里的另一个问题是数据没有与演示完全分离,如果我使用另一个线程,我必须确保我保护共享资源。
因此,主要是通信堆栈将通知应用程序有新数据。这应该由工作线程处理。它运行通信堆栈,处理新消息,然后在更新数据结构时锁定数据结构,然后返回给模块。然后它向主线程发送一条带有 PostMessage 的消息以更新 GUI。
但用户也可以告诉应用程序向外部模块发送数据。这可以通过 3 种方式完成: 1. 发送一次数据。 然后,主线程将向工作线程发送一条消息,以从队列中取出一条消息并将其发送到模块。 2. 定期发送数据。这需要在工作线程内使用计时器,或者一个标志可能就足够了,它会在线程更新函数中的每个循环中发送数据。 3. 向模块发送消息并等待响应。这将需要使用计时器来检查工作线程内的超时。工作线程收到消息后必须通知主线程,以便它可以使用响应更新 GUI。
所以我需要: 1. 在单独的线程中运行通信堆栈。通讯堆栈是一个状态机,一旦检查新数据,调用它就会运行。其中没有while循环。您还可以在其 API 中调用函数来发送数据。
当事情发生时向主线程发送消息以更新 GUI。
向工作线程发送消息,告诉它从应用程序发送数据。
所以我的问题是: 1. MFC 使用 Document/View 模型。我很难找出将其与我想做的事情相匹配的最佳方法,或者我是否想部分放弃它(跳过文档并拥有自己的数据存储方式)。 * 我如何最好地组织我的数据?有一个包含所有应用程序数据的大结构,然后工作线程和主线程在访问它时都必须锁定它? * 当我向主线程发送消息以更新 GUI 时,我如何最好地将消息映射到函数?使用 MESSAGE_MAP?但是消息映射是针对窗口而不是线程的?我需要确定只有主线程才能访问 GUI。我需要将 GUI 中的每个不同更改映射到某个功能。这是很多消息,因为 GUI 中没有统一的显示,而是有很多不同的选项卡(消息日志、对象、自定义消息)。
- 如何处理消息?由于工作线程可以通过正常运行和应用程序告诉它发送消息来访问堆栈,因此我必须在进行另一个调用之前完成对堆栈的一次调用。如果线程更新总是在处理新消息之前完成它所做的事情,这不是问题。或者当计时器命中或我从主线程收到一条新消息并且它也开始处理堆栈时,我是否可能在堆栈内?也许我不仅要为其他线程锁定堆栈,还要确保工作线程本身不会“同时”以两种方式访问它。
【问题讨论】:
-
无法将整个消息放入帖子中,因此请也阅读这些 cmets。2。如何处理消息?由于工作线程可以通过正常运行和应用程序告诉它发送消息来访问堆栈,因此我必须在进行另一个调用之前完成对堆栈的一次调用。如果线程更新总是在处理新消息之前完成它所做的事情,这不是问题。或者当计时器到达时我可能在堆栈内,或者我从主线程收到一条新消息并且它也开始处理堆栈?
-
也许我不仅要为其他线程锁定堆栈,还要确保工作线程本身不会“同时”以两种方式访问它。
-
“定时器回调中不允许系统调用”——谁告诉你的?
-
好吧,我现在找不到资源,但我在某处读到它,发现来源可信。不确定是官方文档还是stackoverflow。一位对Windows编程有很多了解的人也说过。这不是真的吗?使用计时器有几个问题。一个问题是在执行回调时调用了 timeKillEvent。代码中的另一个地方以不同的方式使用计时器。也许我不应该使用 void CALLBACK TimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 ) 而是只使用 OnTimer?
标签: c++ windows mfc thread-safety