我有一个摄像头,我正在把图像实时地读成一个数组。
我正在对图像应用一些算法并将其显示出来。然后我得到下一个图像并显示出来。所以我把图像从摄像机流到显示器。不过,我也希望在显示图像后将其保存到硬盘。我试着用主线,但一切都慢了很多。
然后我尝试使用threadpool(见下面的代码)。这不会降低显示速度,但我发现图像保存不正确。看起来它们不在预期的顺序中,并且在保存了大约50幅图像之后,随后的图像数据看起来乱七八糟。我猜启动的线程太多了。
有更好的办法吗?我想我只需要一个线程来保存图像。可能是某种按顺序保存每个图像的队列。只要它在后台完成,并且不会减慢显示速度。如果有人能发布一段代码片段,那就太棒了。

short[] image1 = new short[20000];
while(streaming)
{
    ReadImageFromCamera(ref image1)
    ImageData data;

    data.fileName = imageNumber;
    data.image = image1;

    ThreadPool.QueueUserWorkItem(WriteImageToFile, data);  // Send the writes to the queue
}


private void WriteImageToFile(object imageData) {

    try {
        ImageData data = (ImageData)imageData;
        System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

        string fName = myDirectory + @"/" + Convert.ToString(data.fileName) + @".spe";

        using (Stream myStream = new FileStream(fName, FileMode.Create)) {
            bf.Serialize(myStream, data.image);
        }
    }
    catch (Exception) { }
}

最佳答案

处理线程时,排序不再由您控制。线程池可以选择按其喜欢的任何顺序调度线程。如果需要按特定顺序顺序顺序执行,那么线程就没有多大意义。
关于损坏的映像,似乎short[] image1实例正在被传递。目前还不清楚ReadImageFromCamera内部发生了什么,但由于您将一个预先初始化的数组传递给它,因此该方法很可能会使用该数组并简单地将数据复制到其中(即使ref关键字表示它可能会创建一个全新的数组实例并将其赋值)。然后在一个单独的线程上将该数组实例传递给WriteImageToFile
同时,平行地,你得到下一个图像。现在您有了一个场景,ReadImageFromCamera可能会在WriteImageToFile将数据存储在磁盘上的同时将数据写入阵列。你的形象被破坏了。通过将新的数组实例传递给WriteImageToFile,可以避免这种情况:

ReadImageFromCamera(ref image1)
ImageData data;

data.fileName = imageNumber;
data.image = (short[])image1.Clone(); // create a new array instance, so that
                                      // the next call to ReadImageFromCamera
                                      // will not corrupt the data

ThreadPool.QueueUserWorkItem(WriteImageToFile, data);

不过,as has been mentioned by Al Kepp因为你只有一个硬盘,所以在这里启动多个线程可能不是最好的选择。您可以考虑使用一个长时间运行的单独线程将数据存储在磁盘上,并将图像放入某种队列中,存储线程从中提取数据并将其写入磁盘。这就带来了处理并发性的一系列问题,限制了队列的大小以及其他什么问题。

07-26 07:19