将新数据传递给可能仍在使用旧数据的异步线程函数
Posted
技术标签:
【中文标题】将新数据传递给可能仍在使用旧数据的异步线程函数【英文标题】:Passing new data to an asynchronous, threaded function that may still be using the old data 【发布时间】:2011-02-25 07:41:24 【问题描述】:我遇到了一些与 C/C++ 相关的问题: 假设我有一些课
class Demo
int constant;
public:
void setConstant(int value)
constant=value;
void submitTask()
// need to make a call to C-based runtime system to submit a
// task which will be executed "asynchronously"
submitTask((void *)&constant);
;
// runtime system will call this method when task will be executed
void func(void *arg)
int constant= *((int *)arg);
// Read this constant value but don't modify here....
现在在我的应用程序中,我执行以下操作:
int main()
...
Demo objDemo;
for(...)
objDemo.setConstant(<somevalue>);
objDemo.submitTask();
...
现在,希望您能看到问题,因为任务应该在异步调用之前立即读取设置的值。由于任务调用是异步的,因此任务可能会读取错误的值,有时会导致意外行为。
我不想仅仅因为这个约束就强制执行同步任务。事先不知道创建的任务数量。我只需要以一种优雅的方式传递这个简单的整数常量,它可以与异步一起工作。显然我无法更改运行时行为(意味着此方法 void func(void *arg)
的签名是固定的)。
提前致谢。
【问题讨论】:
【参考方案1】:如果您不想在进行下一次调用之前等待 C 代码完成,那么您就不能一遍又一遍地重用相同的内存位置。相反,创建一个数组,然后传递这些位置。对于此代码,我将假设 for 循环将运行的次数为 n。在 for 循环运行之前不必知道这一点。
int* values = new int[n];
for(int i=0;i<n;i++)
values[i] = <somevalue>;
submitTask((void*)&values[i]);
稍后,当您确定一切都已完成时,再致电
delete[] values;
或者,或者,创建一个 Demo 对象数组,而不是整数数组。
Demo demo[] = new Demo[n];
for(int i=0;i<n;i++)
demo[i].setConstant(<somevalue>);
demo[i].submitTask();
但第一个对我来说更有意义,因为 Demo 对象似乎并没有做任何有价值的事情。但是您可能遗漏了与问题无关的方法和成员,因此可能会改变哪个选项是最好的。无论如何,关键是如果您不知道它们何时会被使用并且不想等待,那么您需要为单独的值使用单独的内存位置。
【讨论】:
+1: 但在 C++ 中是int *values = new int[n];
和 delete[] values;
,或者更好的是 std::vector<int> values(n);
。
不幸的是,我不能同时执行您提出的两种解决方案,因为我的界面实际上是一个库界面,我也不想修改它。我看到的唯一可能性是在方法 submitTask 中创建一个新内存,例如“new int()”,然后使用它。显然它会导致内存泄漏问题,但我猜这只是可见的方式。
如果您跟踪地址然后删除它们,您可以避免内存泄漏。您可以只创建一个 Vector以上是关于将新数据传递给可能仍在使用旧数据的异步线程函数的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中不使用 ODBC.DataReader 将数据传递给另一个类