将新数据传递给可能仍在使用旧数据的异步线程函数

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&lt;int&gt; values(n); 不幸的是,我不能同时执行您提出的两种解决方案,因为我的界面实际上是一个库界面,我也不想修改它。我看到的唯一可能性是在方法 submitTask 中创建一个新内存,例如“new int()”,然后使用它。显然它会导致内存泄漏问题,但我猜这只是可见的方式。 如果您跟踪地址然后删除它们,您可以避免内存泄漏。您可以只创建一个 Vector 并在创建它们时将地址添加到它们。稍后您可以通过 Vector 对地址调用 delete,然后将它们从 Vector 中删除。 @6502:感谢您的更正。我已将它们包括在内。虽然我喜欢 STL,但在这种情况下,我认为向量不会真正增加太多,因为在循环运行之前应该知道大小。如果它是一个while循环而不是for,我肯定会使用向量,这样我们就不需要先验地知道大小。 vector 的主要特点是在异常情况下不会发生内存泄漏。但是在这种情况下,考虑到一些线程可能已经启动,异常的处理就更加微妙了。

以上是关于将新数据传递给可能仍在使用旧数据的异步线程函数的主要内容,如果未能解决你的问题,请参考以下文章

使用保存的 sklearn 模型进行预测

使用新数据更新 plotly.js 绘图

将异步获取的数据传递给子道具

在 C# 中不使用 ODBC.DataReader 将数据传递给另一个类

是否有将上下文数据传递给@Asynchronous ejb调用的干净方法?

如何使用 IOCP 将用户定义的数据传递给工作线程?