4

在 C/C++ 中,我怎样才能使线程(POSIX pthreads/Windows 线程)给我一个安全的方法,在执行进度或我决定用线程执行的工作时将进度传递回主线程.

是否可以按百分比报告进度?

4

2 回答 2

5

解决此问题的最佳方法是为此使用 C++ 原子。在一些足够明显的地方声明:

std::atomic<int> my_thread_progress(0);

在简单的情况下,这应该是一个静态变量,在更复杂的地方,这应该是管理线程或类似事物的某个对象的数据字段。

在许多平台上,这会有点偏执,因为几乎所有地方的整数读写操作都是原子的。使用原子的位仍然是因为:

  1. 您将保证这在任何平台上都能正常工作,即使是在 16 位 CPU 或任何不寻常的硬件上;
  2. 您的代码将更易于阅读。读者将立即看到这是共享变量,而无需添加任何评论。一旦使用load/store方法更新它,就会更容易了解正在发生的事情。

编辑

英特尔® 64 和 IA-32 架构软件开发人员手册组合卷:1、2A、2B、2C、3A、3B 和 3C ( http://download.intel.com/products/processor/manual/325462.pdf )

第 3A 卷:8.1.1 保证原子操作

Intel486 处理器(以及之后的更新处理器)保证以下基本内存操作将始终以原子方式执行:

  • 读取或写入一个字节
  • 读取或写入在 16 位边界上对齐的字
  • 读取或写入在 32 位边界上对齐的双字
于 2012-10-20T02:59:23.327 回答
5

我将假设一个非常简单的主线程案例和一个函数。我建议每次启动线程时传递一个指向原子的指针(如上面基里尔所建议的)。假设这里是 C++11。

using namespace std;

void threadedFunction(atomic<int>* progress)
{
    for(int i = 0; i < 100; i++)
    {
        progress->store(i);  // updates the variable safely
        chrono::milliseconds dura( 2000 );
        this_thread::sleep_for(dura); // Sleeps for a bit
    }
    return;
}

int main(int argc, char** argv)
{
    // Make and launch 10 threads
    vector<atomic<int>> atomics;
    vector<thread> threads;
    for(int i = 0; i < 10; i++)
    {
        atomics.emplace_back(0);
        threads.emplace_back(threadedFunction, &atomics[i]);
    }

    // Monitor the threads down here
    // use atomics[n].load() to get the value from the atomics
    return 0;
}

我认为那会做你想要的。我省略了轮询线程,但你明白了。我正在传递一个主线程和子线程都知道的对象(在这种情况下是atomic<int>变量),它们都可以更新和/或轮询结果。如果您没有使用完整的 C++11 线程/原子支持编译器,请使用您的平台确定的任何内容,但总有一种方法可以将变量(至少 a void*)传递给线程函数。这就是你如何通过非静态方法来回传递信息的方式。

于 2012-10-20T04:28:20.623 回答