我有一个奇怪的问题,我发现很难调试有时我无法关闭我的程序,当我试图关闭它时冻结。
我制作了一个大型视频图像识别程序。我做了一个特殊按钮来关闭相机。这个按钮通过调用下面的函数来解决这个问题,它确实可以工作。
private void exitcamera()
{
FinalVideo.SignalToStop();
FinalVideo.WaitForStop();
FinalVideo = null;
}
请注意,原始视频是这样开始的
private void buttonStartCamera_Click(object sender, EventArgs e)
{
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
FinalVideo.DesiredFrameRate = 90;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.ProvideSnapshots = true; //snapshots
FinalVideo.Start();
}
现在我的问题似乎(这是一个猜测,因为我无法调试这一刻)一些线程仍然活跃,想要用数据更新主窗体。但是,由于那个正在关闭,它可能无法这样做。我觉得这样的事情正在发生,所以我在主申请表上写了
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// Thread.Sleep(1000); // not sure about these delays might help syncing threads
ExitCamera();
Thread.Sleep(1000);
}
但是,使用最后一个代码,程序退出时会遇到更多麻烦。
我想发送子线程一个退出,但我不知道他们的名字(如果他们有一个名字),我不知道如何列出他们或指示他们停止他们在另一个DLL而不是我的部分代码。从某些dll我没有代码。
那么有没有办法列出子线程然后一个接一个地关闭它们,如果有人按下右上角以退出应用程序?
好吧,我设法调试程序,最后找到导致问题的原因。这有点奇怪,因为作为一个按钮,我可以使用exitcamera
功能停止相机。
但是,在a _formclosing
事件中,虽然在我标记了waitforstop函数之后它仍然有效,但同样的例程并没有起作用。
private void exitcamera()
{
FinalVideo.SignalToStop();
// FinalVideo.WaitForStop(); << marking out that one solved it
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame); // as sugested
FinalVideo = null;
}
我仍然有点困惑,为什么这不会工作,万一结束事件。但它似乎可以解决这个问题。
也许你有事件引起的内存泄漏问题。您可以尝试在退出程序时取消挂钩事件:
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);
也许这会有所帮助。
当我想要显示预览,单击“抓取”按钮,将相机的分辨率从低分辨率更改为高分辨率,抓取图像,然后更改回低分辨率以进行预览时,这有助于另一个问题。这是有效的,即使我不得不放弃它,因为停止和启动相机重置自动曝光,因此图片在抓取的图像上很糟糕:
using AForge.Video;
using AForge.Video.DirectShow;
public partial class Form1 : Form
{
private int PreviewRefreshDelayMS = 40;
private FilterInfoCollection VideoCaptureDevices;
private VideoCaptureDevice CustomerWebcam;
private int CustomerWebcam_CapabilitiesIndexMin;
private int CustomerWebcam_CapabilitiesIndexMax;
private bool bCustomerWebcam_capture;
private Bitmap CustomerWebcam_bitmap;
private System.DateTime CustomerWebcam_nextframetime = DateTime.Now;
public Form1()
{
InitializeComponent();
}
// Some good info to make this more robust
// http://haryoktav.wordpress.com/2009/03/21/webcam-in-c-aforgenet/
//
private void button1_Click(object sender, EventArgs e)
{
CustomerWebcam = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
CustomerWebcam.NewFrame += new NewFrameEventHandler(CustomerWebcam_NewFrame);
int indexMin = -1;
int MinPixels = 0;
int indexMax = -1;
int MaxPixels = 0;
for (int i = 0; i < CustomerWebcam.VideoCapabilities.Length; i++)
{
int pixels = CustomerWebcam.VideoCapabilities[i].FrameSize.Height * CustomerWebcam.VideoCapabilities[i].FrameSize.Width;
if (indexMin == -1) { indexMin = i; MinPixels = pixels; }
if (indexMax == -1) { indexMax = i; MaxPixels = pixels; }
if (pixels < MinPixels) { indexMin = i; MinPixels = pixels; }
if (pixels > MaxPixels) { indexMax = i; MaxPixels = pixels; }
}
CustomerWebcam_CapabilitiesIndexMin = indexMin;
CustomerWebcam_CapabilitiesIndexMax = indexMax;
CustomerWebcam.VideoResolution = CustomerWebcam.VideoCapabilities[indexMin];
CustomerWebcam.DisplayPropertyPage(IntPtr.Zero);
CustomerWebcam.Start();
}
void CustomerWebcam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (CustomerWebcam_bitmap != null)
{
CustomerWebcam_bitmap.Dispose();
CustomerWebcam_bitmap = null;
}
if (bCustomerWebcam_capture)
{
CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone();
System.Random rnd = new Random();
CustomerWebcam_bitmap.Save("img" + Convert.ToString((int)(rnd.NextDouble() * 10000000)) + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
bCustomerWebcam_capture = false;
((Bitmap)eventArgs.Frame).Dispose();
}
else
if (DateTime.Now > CustomerWebcam_nextframetime)
{
CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = CustomerWebcam_bitmap;
CustomerWebcam_nextframetime = DateTime.Now.AddMilliseconds(PreviewRefreshDelayMS);
((Bitmap)eventArgs.Frame).Dispose();
}
}
private void Form1_Load(object sender, EventArgs e)
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
{
comboBox1.Items.Add(VideoCaptureDevice.Name);
}
comboBox1.SelectedIndex = 0;
}
private void button2_Click(object sender, EventArgs e)
{
CustomerWebcam.SignalToStop();
CustomerWebcam = null;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!(CustomerWebcam == null))
if (CustomerWebcam.IsRunning)
{
CustomerWebcam.SignalToStop();
CustomerWebcam = null;
}
}
private void button4_Click(object sender, EventArgs e)
{
bCustomerWebcam_capture = true;
}
}
还有一件事要提到...... AForge库是我能够找到的最稳定的方式,可以使用网络摄像头抓取静止图像并保存为JPEG而无需深入研究Windows 8 metro应用程序的世界。我希望使用OpenCV.NET,或者只是使用DirectShow或WIA的常规.NET API,但这是最简单的,它对我有用。
这里有一些很难找到但很有用的好样本:https://github.com/mdavid/aforge.net
我正在处理这个问题。这是一种停止相机并关闭Win Form的简单方法。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalVideo != null)
{
if (FinalVideo.IsRunning)
{
FinalVideo.SignalToStop();
FinalVideo = null;
}
}
}
在我的情况下,需要WaitForStop(),但代码执行在方法内部消除。我在调用SignalToStop()后立即将其替换为:
while (m_Device.IsRunning) { }
这是AForge库中涉及的代码:
public bool IsRunning
{
get
{
if (this.thread != null)
{
if (!this.thread.Join(0))
{
return true;
}
this.Free();
}
return false;
}
}
public void WaitForStop()
{
if (this.thread != null)
{
this.thread.Join();
this.Free();
}
}
编辑:这没有解决挂起100%的时间。有时,在WorkerThread()方法上调用com对象(mediaControl.Stop();)只是永远。
避免与表单直接交互 - 希望有一个比计时器更好的解决方案,但解决问题。一世
静态助手类
public static Bitmap StaticBitmap = new Bitmap(100,100);
形成
public void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
lock (StaticHelper.StaticBitmap)
{
using (Bitmap b = (Bitmap)eventArgs.Frame)
{
StaticHelper.StaticBitmap = (Bitmap)b.Clone();
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
lock (StaticHelper.StaticBitmap)
{
pictureBox1.Image = (Bitmap)StaticHelper.StaticBitmap.Clone();
}
}
这会破坏你的问题(我有这个问题,我试过)
using System.Threading;
bool photo_was_taken = false;
private void buttonStartCamera_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(exitcamera));
thread.Start();
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
FinalVideo.DesiredFrameRate = 90;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.ProvideSnapshots = true; //snapshots
FinalVideo.Start();
}
private void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// what you want to do ( your code is here )
photo_was_taken = true;
}
private void exitcamera()
{
while (!photo_was_taken)
{
Thread.Sleep(5); // you can change wait milliseconds
}
FinalVideo.SignalToStop();
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);
//FinalVideo.WaitForStop();
while (FinalVideo.IsRunning)
{
FinalVideo.Stop();
// FinalVideo = null; >> // that is not condition
}
}