C#增加相机图像处理的内存
我有一个增加记忆力的问题。我有一张来自照相机的图像。图像由具有非托管代码的函数处理。如果找不到预期的模式,则此函数需要很长时间(几秒钟)。如果可以找到模式,它会很快返回结果(有些毫秒) 我尝试在一个新的C#增加相机图像处理的内存,c#,thread-safety,C#,Thread Safety,我有一个增加记忆力的问题。我有一张来自照相机的图像。图像由具有非托管代码的函数处理。如果找不到预期的模式,则此函数需要很长时间(几秒钟)。如果可以找到模式,它会很快返回结果(有些毫秒) 我尝试在一个新的线程中启动后处理,并在200毫秒后中止它。到目前为止,这是可行的。现在我的问题是,我的记忆力在增长。可能using子句没有按预期工作,图像保存在内存中 private void ImageWorker() { while (_imageWorkerRunning) {
线程中启动后处理
,并在200毫秒后中止它。到目前为止,这是可行的。现在我的问题是,我的记忆力在增长。可能using
子句没有按预期工作,图像保存在内存中
private void ImageWorker()
{
while (_imageWorkerRunning)
{
try
{
using (var img = CameraHelper.GetImage())
{
var waiter = new ManualResetEvent(false);
ProcessResult result = null;
var thd = new Thread(() => {
result = UnManagedImageProcessor.Process(img);
waiter.Set();
});
thd.Start();
waiter.WaitOne(200);
if (thd.ThreadState == ThreadState.Running || result == null)
{
thd.Abort();
while (thd.ThreadState != ThreadState.Aborted) new ManualResetEvent(false).WaitOne(10);
}
Application.Current.Dispatcher.Invoke(() => DisplayImage = img);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
GC
在中止的线程上工作正常吗?我想这可能是我的问题
解决方案:
我将代码更改为以下内容。现在我有两个并行任务。首先是获取图像并检查处理是否可用
如果是,图像将提供给此ImageProcessing
任务。仅在Success
上显示图像(这样处理速度很快,每个图片都可以处理)
如果处理未成功,则需要一些时间,并且图像仅显示为实时图像(由ImageWorker
)
谢谢你的帮助。我建议你使用 要显示可以使用锁定器的图像,每次用户界面空闲时,锁定对象,获取最后一个图像并处理上一个图像。此外,每次处理图像时,您都会锁定对象并将var设置为最后一个 显示逻辑:
readonly object lastProcessdImageLocker = new object();
Bitmap lastProcessdImage;
//Every time a image process is done:
lock(lastProcessdImageLocker)
lastProcessdImage = imageJustProcessed;
//Every time the UI thread is idle
lock(lastProcessdImageLocker)
myPictureboxImage = lastProcessdImage;
//Here you should also dispose the previus myPictureboxImage so you prevent your memory usage to grow fast!
使用BlockingCollection消费(处理)相机图像的示例代码:
BlockingCollection<Bitmap> cameraImages = new BlockingCollection<Bitmap>();
如果您的cameraImages计数增长过快(内存不足),则需要缩短处理时间或停止相机一段时间。您可能希望使用
water.WaitOne(200)
的结果,而不是检查线程状态和结果变量。如果WaitOne超时,则不应触摸结果。(跨线程访问)DisplayImage=img做什么?它是一个具有集合逻辑的属性吗?我猜你正在泄漏GDI资源。但是这里没有足够的代码来说明。例如,正如Jeroen所问,DisplayImage做什么?或非托管DimageProcessor。进程?中止线程是错误的。若方法正在分配一些内存,而您中止了它,该怎么办?当然,它不会被发布=问题。相反,您可以让线程完成其工作,但限制允许在后台继续工作的线程数。或者只是等待一个,但异步填充图像。至于同步Monitor。输入/Leave
is。另外,您应该在threadmethod中添加一个try/catch
。看起来很棒。我试试这个。明天(当我再次工作时)我会给出反馈!谢谢你的回答。这帮助我找到了一个单独处理循环的解决方案。我很高兴能帮助您。您使用了BlockingCollection?我更新了我的问题并添加了我的解决方案(如您所见)。我只是采用了独立图像处理循环的方法。
BlockingCollection<Bitmap> cameraImages = new BlockingCollection<Bitmap>();
void StartProcess()
{
if (processImageThread== null || !processImageThread.IsAlive)
{
processImageThread= new Thread(ProcessLoop);
processImageThread.Name = "ProcessLoop";
processImageThread.IsBackground = true;
processImageThread.Start();
Console.TraceInformation("ProcessLoop started");
}
}
private void ProcessLoop()
{
try
{
foreach (img in cameraImages.GetConsumingEnumerable(CancelProcessing.Token))
{
// Do your stuff
}
}
catch (OperationCanceledException)
{
Console.WriteLine("ProcessLoop OperationCanceledException.");
}
finally
{
}
}