如何在更新 GTK UI 的 GTask 结束时避免竞争条件?

问题描述

我正在构建一个 gtk3 应用程序,并试图找出在更新 UI 的 GTask 完成时避免竞争条件。

由于 data_acq() 调用函数 (GTask) 长时间运行,我有一个更新的进度条(通过 gdk_threads_add_timeout(progressBar_timeout_cb)),但在 {{1 }} 我使用 data_acq() 将进度条设置为 100%。问题在于 gdk_threads_add_idle(progressBar_complete,params) 的最后一步是自动调用 GTask,它释放指向进度条的指针,当 free_data_acq_data(params) 触发时会导致段错误,如果它发生 progressBar_complete(params) 发生之后。

这个问题可能完全是由于我滥用指针(或其他一些菜鸟错误),但我承认我没有看到如何以保证 1) 数据被释放的方式传递数据使用后和 2) 不会过早释放。请注意,任务可能被取消,因此我不想释放 free_data_acq_data(params) 中的内存。

所以我的问题是:在这种情况下是否有更好的方法来避免竞争条件(或者是否有另一种方法来构建代码以避免此问题)?或者是否有一种机制可以检查 progressBar_complete() 函数是否已完成,以便我可以告诉内存释放函数等待 gdk_threads_add_idle() 完成?

我尝试使用全局来跟踪 idle 是否已运行,但我无法让它与 progressBar_complete 完美配合,因为这意味着 GTask 从未完成(因为线程从未被放弃给 free_data_acq_data 来更新全局)。

为了具体起见,这里是一些示例代码

progressBar_complete

解决方法

如果您需要从 UI 线程访问进度条指针,那么我建议不要在工作线程中释放它。也许当任务完成或取消时,您可以使用 gdk_threads_add_idle() 来排队另一个函数,该函数将释放 UI 端使用的资源,例如 dataAcqParams,而不是在工作线程中释放它?>