我有一个必须完全运行的功能,不会中断,并返回一个结果.如果异步事件导致在它仍在执行时再次调用它,则必须以某种方式阻止该调用,直到第一次调用完成.
互斥?别的什么?
[更新]该函数在我的主表单类中,并从类的两个方法调用:一个处理从serail端口读取的数据,另一个处理计时器到期.这两个似乎都在他们自己的线程中运行,因为一个函数的调用可以被另一个调用中断(对我来说,在应用程序级别,它们只是我在设计时放在主表单上的组件).
也许TCriticalSection?(但谷歌搜索不清楚我是否需要使用acquire/release或'进入/离开',似乎因为代码是一个简单的函数可能是mainform,它将是可重入的).
也许我要求的是一种使代码"不可重入"的方法,阻止直到第一次完成?无论答案是什么,我认为我将需要一个代码示例,或UTl到一个:-(
(请注意,此页面提供了大量有用的信息(我不会全部了解,但它对其他人来说非常有用))
[更新]这与GUI更新无关,只是每个发送一些TCOP数据的事件都应该接收响应.
虽然该应用程序有一个GUI - 它是基于表单的 - 只是在我想显示一些调试信息的情况下,因为该应用程序将在没有监视器的PC上运行(是的,我知道它stil有一个GUI,但是不是我的问题/点)
将函数移动到没有异步事件的单独工作线程.
主线程中的异步事件应该将一些消息发布到某个队列中,因此当工作线程完成执行时,主线程将使用新参数再次启动它.
有更多信息的更新.假设(猜测)这些函数通过RS232或者什么都没有接收数据,并且正在做类似GUI更新的事情,我将草拟以下方法.
更多细节:
因此,RS232事件处理程序将从COM读取数据,将其放入TBytes,然后将该数据包添加到输入TQueue.更复杂的方法是查看Queue是否已经包含来自COM的数据并使用旧数据聚合新数据包而不是将新数据包分开.这需要更仔细的锁定,所以在这里聚合可能只是不值得蜡烛
定时器甚至会使空数据包(零长度字节数组)并将其排队.如果该计时器甚至还有一些数据要通过 - 那么它应该是变量记录或单独的输入队列或其他什么.但没有信息似乎计时器只发送信息,但警报本身
根据你的话,Timer和RS232事件都在它们各自的线程中工作.我对此有疑问,但我必须相信你.
在将工作负载排入队列后(例如在输入队列的通知事件中),我将执行win32 PostMessage(MainForm.Handle,work_request).毕竟我们想在一个地方集中线程控制.要保持线程隔离消息应该发布,没有SendMessage没有TControl.Perform!
在表单的work_request处理程序的主线程中,我将查看输入队列是否已经为空.如果没有,那么我会查看工作线程状态.如果它被暂停,我会恢复它.
工作线程看起来是输入队列有什么东西,而它有,它会:
如果输入队列为空,则该函数退出,该线程执行PostMessage Work_EmptyQueue并暂停,直到稍后将被唤醒以执行更多工作或释放.
当MainForm(再次在主线程中)收到Work_Complete时
如果输出队列为空,则省略步骤2和3(如果在前一步骤中发生合并,则将省略).但不是第四.步骤1和2是分开的.由于队列操作是线程互锁的,因此步骤1的目标是尽可能快地提取数据.Margine将在当地完成.
当MainForm收到Work_EmptyQueue时,它会检查输入队列现在是否为空,并且可能会恢复工作线程.它可以选择进行状态或其他任何GUI更新.
这是一个粗略的草图.它可以更好地雕刻给你某些cituation.
假设您担心来自同一线程的重入,那么阻止重入调用将导致典型的死锁.如果这是您的方案,那么您需要执行以下操作之一:
很可能这些选项都没有吸引你!
如果您担心来自不同线程的同时调用,那么您可以使用某种锁.例如,在Windows上,您通常会使用关键部分.
使用两种机制的组合:
| 归档时间: |
|
| 查看次数: |
604 次 |
| 最近记录: |