我有一个摄像头,我正在把图像实时地读成一个数组。
我正在对图像应用一些算法并将其显示出来。然后我得到下一个图像并显示出来。所以我把图像从摄像机流到显示器。不过,我也希望在显示图像后将其保存到硬盘。我试着用主线,但一切都慢了很多。
然后我尝试使用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因为你只有一个硬盘,所以在这里启动多个线程可能不是最好的选择。您可以考虑使用一个长时间运行的单独线程将数据存储在磁盘上,并将图像放入某种队列中,存储线程从中提取数据并将其写入磁盘。这就带来了处理并发性的一系列问题,限制了队列的大小以及其他什么问题。