1

我需要将进程的标准输出(二进制数据)放入字符串缓冲区并在另一个线程中使用它。

这是制作人:

while (ReadFile(ffmpeg_OUT_Rd, cbBuffer, sizeof(cbBuffer), &byteRead, NULL)){
    tByte += byteRead;   //total bytes
    sb->sputn(cbBuffer, byteRead);
}
m_bIsFinished = true;
printf("%d bytes are generated.\n", tByte);

这是消费者:

while (!PCS_DISPATCHER_INSTANCE->IsFinished())
    Sleep(200);
Sleep(5000);
Mystringbuf* sb = PCS_DISPATCHER_INSTANCE->sb;
printf("Avail: %d\n", sb->in_avail());

事实证明,消费者无法获得生产者生产的所有字节。( tByte <> sb->in_avail())

这是一种内部缓冲问题吗?如果是,如何强制 stringbuf 刷新其内部缓冲区?

4

1 回答 1

3

Astreambuf与flush 完全不同:直接写入缓冲区。pubsync()如果您要使用派生的对象(例如 filebuf),则有一个成员可以提供帮助。但这不适用于您的情况。

您的问题肯定来自or上的数据竞赛。通过互斥体或通过. 如果不是原子的,并且取决于您的实现,线程之间的同步可能无法得到保证(例如:生产者可以写入内存,但消费者仍然从 CPU 内存缓存中获得过时的值),这可能会导致这样的数据竞赛。 sputn()is_avail()atomicm_bIsFinishedisFinished()

编辑:

如果您在单个线程中遇到问题,从而消除了任何潜在的竞争情况,它可能来自streambuf. 我可以在单线程应用程序中使用 MSVC13 体验这一点:

  • 跟踪显示读取的字节数是准确的,但in_avail()在整个循环中结果总是小于或等于 tByte。
  • 读取 streambuf 时,读取了正确的总字节数(因此超过了 in_avail() 指示的字节数)。

此行为是合规的。根据 C++ 标准:如果读取位置可用in_avail(),则返回 egptr() - gptr() ,否则返回 showmanyc()。 后者被定义为返回序列中可用字符数的估计值。 给出的唯一保证是您可以在不遇到 eof 的情况下读取至少in_avail()字节。

变通方法用于sb->pubseekoff(0,ios::end)- sb->pubseekoff(0,ios::beg);计算可用字节数,并确保在读取 streambuf 之前重新定位到 sb->pubseekoff(0,ios::beg)。

于 2014-09-14T12:48:21.740 回答