我在使用Winform7.0开发海康相机应用的时候系统悄无声息的退出
一、简介
1、说明一下
最近,我在开发一个玻璃幕墙检测的项目,这个项目需要使用到海康的相机系统。业务是这样的,相机按着指定的坐标,扫描玻璃幕墙的每块玻璃,通过算法查看是否有损坏的,如果有就发出报警信息,告诉客户。这个项目是有一个同事写好的,我后来重构了一下,但是运行起来,运行若干次,就退悄无声息的退出软件,什么也不提示。通过这个现象,我知道肯定是和硬件交互的时候出了问题,而且抛出任何异常。海康的日志文件也没有显示是什么有价值的东西。
但是,通过努力的查找,调试,排除,终于找到了问题的关键,我们有四个相机,就有四个回调函数,用于处理图像,但是每个相机注册了一个自己的回调,应该是四个相机,设置四个回调,但是回调函数的实例是一个,否则就会出现程序毫无征兆的崩溃。
2、开发平台
开发工具:Visual Studio2022
开发语言:C#
开发平台:Winform 7.0
海康类库:MvCamCtrl.NET
二、详细步骤
这个问题搞了我两天才搞定,但是搞定了,心里舒服了。今天就把思路写下来,自己可以查找,也可以帮助大家。
知道问题的关键点了,解决也就方便了。这也叫难着不会,会的不难。
1、一定要把 MyCamera.cbOutputExdelegate 声明为类的成员。
private MyCamera.cbOutputExdelegate _outputImageDelegate;
1 #region 私有实例字段
2
3 private MyCamera[]? _myCameras;//相机实例的数组。
4 private MyCamera.MV_CC_DEVICE_INFO_LIST _deviceInformationList;//相机信息的列表
5
7 //图片文件的存储路径:根目录/当前扫描时间(作为目录)/相机编号
8 private string? _saveImageBaseDirectory; //图像文件存储的根路径路径。
9 private string? _saveImageOnceTimeDirectory; //单次扫描图像文件的存储路径,目录结构:根目录+当前扫描时间
10 private string[]? _saveImageForCameraDirectory;//最终存储图片文件的路径,目录结构:根目录+当前扫描时间+相机序列号(有多少台相机,就有多少个目录)
11 private IntPtr[]? _imageDisplayHandles;//针对每台相机图像进行显示处理,应为有多台,所以是数据类型是数组。
14 private MyCamera.cbOutputExdelegate _outputImageDelegate;
17 #endregion
2、一定要在构造函数里初始化,当然,如果你可以保证一个实例,就可以放在其他地方,我是为了方便,没有过多的设计。
_outputImageDelegate = new MyCamera.cbOutputExdelegate(SaveImageCallBack);
1 /// <summary>
2 /// 初始化新实例。
3 /// </summary>
4 public frmMonitoring()
5 {
6 InitializeComponent();
7 _outputImageDelegate = new MyCamera.cbOutputExdelegate(SaveImageCallBack);
8 _patrolProcessor = new OrientalMotorPatrolProcessor();
9
10
11 #region 全局异常处理
12
13 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
14 Application.ThreadException += Application_ThreadException;
15
16 #endregion
17 }
这是附送的方法,异常处理。
1 #region 异常处理
2
3 /// <summary>
4 /// 该方法处理用于处理 Windows 窗体线程引发的异常。
5 /// </summary>
6 /// <param name="sender"></param>
7 /// <param name="e"></param>
8 /// <exception cref="NotImplementedException"></exception>
9 private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
10 {
11 try
12 {
13 ShowPromptMessage(e.Exception.Message);
14 }
15 catch (Exception)
16 {
17 try
18 {
19 ShowPromptMessage("不可恢复的非 Windows 窗体线程异常,应用程序将退出!");
20 }
21 finally
22 {
23 Application.Exit();
24 }
25 }
26 }
27
28 /// <summary>
29 /// 使用该方法处理非UI线程所发生的异常。
30 /// </summary>
31 /// <param name="sender"></param>
32 /// <param name="e"></param>
33 /// <exception cref="NotImplementedException"></exception>
34 private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
35 {
36 try
37 {
38 var exceptionObject = e.ExceptionObject as Exception;
39 if (exceptionObject != null)
40 {
41 ShowPromptMessage(exceptionObject.Message);
42 }
43 }
44 catch (Exception)
45 {
46 try
47 {
48 ShowPromptMessage("不可恢复的非 Windows 窗体线程异常,应用程序将退出!");
49 }
50 finally
51 {
52 Application.Exit();
53 }
54 }
55
56 }
57
58 #endregion
辅助方法。
1 /// <summary>
2 /// 用于显示系统的提示信息,包括异常信息、操作信息等。
3 /// </summary>
4 /// <param name="message">需要显示的信息内容。</param>
5 /// <param name="stateCode">具体操作的状态码值,该值可有可无,不是所有操作都有状态值的,默认值:0,表示没有状态值。</param>
6 private void ShowPromptMessage(string message, int stateCode = 0)
7 {
8 string resultMessage;
9 if (stateCode == 0)
10 {
11 resultMessage = $"{message}\r\n";
12 }
13 else
14 {
15 resultMessage = $"{message}: Error ={string.Format("{0:X}", stateCode)}";
16 }
17
18 switch (stateCode)
19 {
20 case MyCamera.MV_E_HANDLE: resultMessage += ",错误或无效句柄(Error or invalid handle)\r\n"; break;
21 case MyCamera.MV_E_SUPPORT: resultMessage += ",不支持的功能(Not supported function)\r\n"; break;
22 case MyCamera.MV_E_BUFOVER: resultMessage += ",缓存已满(Cache is full)\r\n"; break;
23 case MyCamera.MV_E_CALLORDER: resultMessage += ",函数调用顺序错误(Function calling order error)\r\n"; break;
24 case MyCamera.MV_E_PARAMETER: resultMessage += ",不正确的参数(Incorrect parameter)\r\n"; break;
25 case MyCamera.MV_E_RESOURCE: resultMessage += ",应用资源失败(Applying resource failed)\r\n"; break;
26 case MyCamera.MV_E_NODATA: resultMessage += ",没有数据(No data )\r\n"; break;
27 case MyCamera.MV_E_PRECONDITION: resultMessage += ",前提条件错误,或运行环境已更改(Precondition error, or running environment changed)\r\n"; break;
28 case MyCamera.MV_E_VERSION: resultMessage += ",版本不匹配(Version mismatches)\r\n"; break;
29 case MyCamera.MV_E_NOENOUGH_BUF: resultMessage += ",内存不足(Insufficient memory)\r\n"; break;
30 case MyCamera.MV_E_UNKNOW: resultMessage += ",未知错误(Unknown error)\r\n"; break;
31 case MyCamera.MV_E_GC_GENERIC: resultMessage += ",一般错误(General error)\r\n"; break;
32 case MyCamera.MV_E_GC_ACCESS: resultMessage += ",节点访问条件错误(Node accessing condition error)\r\n"; break;
33 case MyCamera.MV_E_ACCESS_DENIED: resultMessage += ",没有权限(No permission)\r\n"; break;
34 case MyCamera.MV_E_BUSY: resultMessage += ",设备正忙或网络断开连接(Device is busy, or network disconnected)\r\n"; break;
35 case MyCamera.MV_E_NETER: resultMessage += ",网络错误(Network error)\r\n"; break;
36 }
37
38 SetAsyncControlText(txtExceptionMessage, $">> {resultMessage}", true);
39 }
3、实例化相机,并初始化回调函数。
1 MyCamera.MV_CC_DEVICE_INFO[] _deviceInfoArray = new MyCamera.MV_CC_DEVICE_INFO[localDeviceCount];
2 object? localDeviceInfo = null;
3 MyCamera.MV_CC_DEVICE_INFO device;
4
5 for (int i = 0; i < localDeviceCount; ++i)
6 {
7 if (_deviceInformationList.pDeviceInfo != null && _deviceInformationList.pDeviceInfo.Length > 0)
8 {
9 localDeviceInfo = Marshal.PtrToStructure(_deviceInformationList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
10 if (localDeviceInfo != null)
11 {
12 //获取选择的设备信息
13 device = (MyCamera.MV_CC_DEVICE_INFO)localDeviceInfo;
14
15 //打开设备
16 if (cameras[i] == null)
17 {
18 cameras[i] = new MyCamera();
19 }
20
21 stateCode = cameras[i].MV_CC_CreateDevice_NET(ref device);
22 if (MyCamera.MV_OK != stateCode)
23 {
24 return;
25 }
26
27 stateCode = cameras[i].MV_CC_OpenDevice_NET();
28 if (MyCamera.MV_OK != stateCode)
29 {
30 return;
31 }
32 else
33 {
34 _deviceInfoArray[i] = device;
35 // 探测网络最佳包大小(只对GigE相机有效),我们是USB相机
36 if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
37 {
38 int nPacketSize = cameras[i].MV_CC_GetOptimalPacketSize_NET();
39 if (nPacketSize > 0)
40 {
41 stateCode = cameras[i].MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
42 if (stateCode != MyCamera.MV_OK)
43 {
44 ShowPromptMessage("Warning: Set Packet Size failed {0:x8}", stateCode);
45 }
46 }
47 else
48 {
49 ShowPromptMessage("Warning: Get Packet Size failed {0:x8}", stateCode);
50 }
51 }
52
53 //1、开启设置触发模式
54 SetCameraTriggerMode(cameras[i]);
55 //2、设置具体的触发模式为软触发
56 SetCameraTriggerSource(cameras[i]);
57 cameras[i].MV_CC_RegisterImageCallBackEx_NET(_outputImageDelegate, i);
58 }
59 }
60 }
61 }
4、回调方法的实现。
回调的方法可以根据自己的需求编写,这是我的需求,我的具体编写方法,不能照抄。
1 /// <summary>
2 /// 获取帧数据并保存为图像的回调函数。
3 /// </summary>
4 /// <param name="frameData">图像的帧数据。</param>
5 /// <param name="frameInfo">图像的帧信息。</param>
6 /// <param name="cameraIndex">相机的索引,因为有多台相机。</param>
7 private void SaveImageCallBack(IntPtr frameData, ref MyCamera.MV_FRAME_OUT_INFO_EX frameInfo, IntPtr cameraIndex)
8 {
9 int _cameraIndex = (int)cameraIndex;
10
11 if (_perCameraTotalFrames != null && _perCameraTotalFrames.Length > 0)
12 {
13 //抓取的帧数
14 ++_perCameraTotalFrames[_cameraIndex];
15
16 //第一个相机数据,每台相机处理的数据是一样的,随机选择第一个,作为结果输出。
17 if (_cameraIndex == 0)
18 {
19 SetAsyncControlText(lblAcquisitionCountValue, _perCameraTotalFrames[_cameraIndex].ToString());
20 }
21 }
22
23 //显示图像
24 //将相机图像显示到对应的位置
25 if (_imageDisplayHandles != null && _imageDisplayHandles.Length > 0)
26 {
27 MyCamera.MV_DISPLAY_FRAME_INFO displayFrameInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
28 displayFrameInfo.hWnd = _imageDisplayHandles[_cameraIndex];
29 displayFrameInfo.pData = frameData;
30 displayFrameInfo.nDataLen = frameInfo.nFrameLen;
31 displayFrameInfo.nWidth = frameInfo.nWidth;
32 displayFrameInfo.nHeight = frameInfo.nHeight;
33 displayFrameInfo.enPixelType = frameInfo.enPixelType;
34
35 if (_myCameras != null && _myCameras.Length > 0)
36 {
37 CameraDisplayOneFrame(_myCameras[_cameraIndex], ref displayFrameInfo);
38 }
39 }
40
41 //判断当前相机是否允许保存图像
42 if (_isPerCameraSaveImage != null && _isPerCameraSaveImage.Length > 0)
43 {
44 if (_isPerCameraSaveImage[_cameraIndex] && _saveImageForCameraDirectory != null && _saveImageForCameraDirectory.Length > 0 && _perCameraSerialNumbers != null && _perCameraSerialNumbers.Length > 0)
45 {
46 MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveToFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
47
48 stSaveToFileParam.enPixelType = frameInfo.enPixelType;
49 stSaveToFileParam.pData = frameData;
50 stSaveToFileParam.nDataLen = frameInfo.nFrameLen;
51 stSaveToFileParam.nWidth = frameInfo.nWidth;
52 stSaveToFileParam.nHeight = frameInfo.nHeight;
53
54 stSaveToFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp;
55 stSaveToFileParam.nQuality = 100;
56 //图像文件名应包含采集时间、对应相机ID号、玻璃编号等信息
57 var saveImageFullPath = $"{_saveImageForCameraDirectory[_cameraIndex]}\\{DateTime.Now.ToString("yyyyMMddHHmmss")}_{_perCameraSerialNumbers[_cameraIndex]}_{_patrolFileGlassNumber}.bmp";
58 stSaveToFileParam.pImagePath = saveImageFullPath;
59
60 if (_myCameras != null && _myCameras.Length > 0)
61 {
62 _myCameras[_cameraIndex].MV_CC_SaveImageToFile_NET(ref stSaveToFileParam);
63 CameraSaveImageToFile(_myCameras[_cameraIndex], ref stSaveToFileParam);
64 }
65 }
66 }
67 }
三、总结
我已经实验过单相机回调没问题了,所以多相机就直接复制了多个回调,因此相机回调还没传到外面的实例,就已经崩了,肯定就是封装的问题。看了海康的多相机demo,相机有4个实例,回调函数只有一个实例,4个相机注册了四次回调,但都是同一个回调实例。这就是我发生错误的根本原因。
好了,问题解决了,又学了点技术,继续努力,苍天不负努力的人。
我在使用Winform7.0开发海康相机应用的时候系统悄无声息的退出的更多相关文章
- 海康相机开发(1) SDK安装和开发
1.1 安装包获取 从官网下载最新版本的MVS安装包,支持Windows xp.Windows 7.Windows 8.Windows 10的32和64位系统.安装过程默认即可. 官网下载链接:htt ...
- 【miscellaneous】海康相机RTSP连接代码分析
海康相机RTSP连接代码分析 最近在做海康相机rtsp连接获取音视频的工作,现在介绍一下分析过程和源码. [源码在我上传的共享资料中: http://download.csdn.net/detail/ ...
- RTSP配置海康相机视频
RTSP:即时串流协定(Real Time Streaming Protocol,RTSP)是用来控制声音或影像的多媒体串流协议,并允许同时多个串流需求控制. 1.获取海康相机ip地址 (1).下载海 ...
- Java二次开发海康SDK-对接门禁机
写在最前 SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64 参考文档:海康SDK使用手册_V6.1 对接测试设备型号:DS-K1T671M 设备序列号:E5 ...
- 海康相机SDK二次开发只有视频无声音问题
海康SDK相信做企业开发的的同仁,在项目中经常会用到,毕竟使用范围这么广. 本次就开发遇到的奇葩问题来说明一下我们的解决方案. 场景 虽然海康有4200客户端,但是对于高度定制化的项目,肯定不能再使用 ...
- 配置海康相机SDK文件
前言 项目使用到海康摄像机,进行二次开发需要首先对SDK文件进行相关配置. 实现过程 1.下载SDK开发包: 网址:http://www.hikvision.com/cn/download_61.ht ...
- (HK1-2)海康相机直接连接电脑不经过路由器设置
解决电脑无法通过网线直连海康摄像机的问题 https://blog.csdn.net/u014552102/article/details/86708371 一.现象: 通过博主的另外一篇博客h ...
- rtsp学习----海康RTSP客户端连接深入分析
转载于:http://blog.csdn.net/zhouyongku/article/details/41546789 海康相机RTSP连接代码分析 最近在做海康相机rtsp连接获取音视频的工作,现 ...
- win10 64 + VS2010 + Opencv 2.4.9 + HIKVISION(海康)
海康相机型号:DS-2CD2512F-IS 参考连接http://blog.csdn.net/wanghuiqi2008/article/details/31404571 先上效果图 其中,在连接时遇 ...
- SecureCrt使用SSH2登陆海康相机
海康相机登陆SSH2: 1.安装SecureCRT2.登陆到相机,系统-安全管理-安全服务,勾选启用SSh3,打开SecureCRT,快速链接4.选择协议SSh2,主机Ip填入相机IP,端口默认22, ...
随机推荐
- python之爬虫三
20xpath入门 在编写爬虫程序的过程中提取信息是非常重要的环节,但是有时使用正则表达式无法匹配到想要的信息,或者书写起来非常麻烦,此时就需要用另外一种数据解析方法,也就是本节要介绍的 Xpath ...
- [Linux]CentOS7(LiveGnome版)配置网络
话接上一回合,刚通过U盘启动盘安装CentOS7(LiveGnome)完成后,访问不了网络.肿么办?且听咱慢慢道来. 咱平时都是使用(有线网络)网卡,通过公司分配的固定IP地址(包括:固定主机IP.固 ...
- 【Voyage】GDOI 2023 旅游记 || ECHO.
\(\color{#FFFFFF}{那是什么样的旅途呢}\) \(\color{#FFFFFF}{真的会害怕很多东西呢.想想害怕的其实不止这样一件事,便产生了"其实都一样没关系的,都应该踏过 ...
- Java并发(一)----进程、线程、并行、并发
一.进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存.在指令运行过程中还需要用到磁盘.网络等设备.进程就是用来加载指令.管理内存.管理 ...
- servlet 没有实例化可以直接调用非静态方法??
今天练习servlet时,居然发现没有实例化可以直接调用非静态方法.看了好长时间发现:省去了this关键字.记录一下. public class Servlet2 extends GenericSer ...
- selenium部分知识点总结
selenium部分总结 最近写了一个selenium自动化脚本. 基于此总结一些常用的代码 1. 用户输入换行符不终止输入 strings = '' s = input('请输入:(q停止输入)') ...
- 执行sql报lock wait timeout exceeded; try restarting transaction
mysql查询时候报错: Lock wait timeout exceeded; try restarting transaction 译文:锁等待超时;试着重新启动事务 被锁了,需要解锁. 1.in ...
- 揭开神秘面纱,会stream流就会大数据
目录 准备工作 1.map类 1.1 java stream map 1.2 spark map 1.2.1 MapFunction 1.2.2 MapPartitionsFunction 2.fla ...
- [Pytorch框架] 2.4 卷积神经网络简介
文章目录 2.4 卷积神经网络简介 2.4.1 为什么要用卷积神经网络 2.4.2结构组成 卷积层 卷积计算 卷积核大小 f 边界填充 (p)adding 步长 (s)tride 计算公式 卷积层 激 ...
- YOLO4论文中文版
文章目录 YOLO4论文中文版 摘要 1.介绍 2.相关工作 2.1.目标检测模型 2.2.Bag of freebies 2.3.Bag of specials 3.方法 3.1.架构选择 3.2. ...