wpf 单例模式和异常处理 (原发布 csdn 2017-04-12 20:34:12)
第一次写博客,如有错误,请大家及时告知,本人立即改之。
如果您有好的想法或者建议,我随时与我联系。
如果发现代码有误导时,请与我联系,我立即改之。
好了不多说,直接贴代码。
一般的错误,使用下面三个就可以了。我不太赞同项目里面大量使用try{}catch{}(释放资源除外)
// 设置UI线程发生异常时处理函数
System.Windows.Application.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
// 设置非UI线程发生异常时处理函数
AppDomain.CurrentDomain.UnhandledException += App_CurrentDomainUnhandledException;
// 设置托管代码异步线程发生异常时处理函数
TaskScheduler.UnobservedTaskException += EventHandler_UnobservedTaskException;
特殊情况下,此函数可检测到c++封装的dll(不是百分之百可以检测到)
public delegate int CallBack(ref long a);
CallBack myCall;
[DllImport("kernel32")]
private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);
// 设置非托管代码发生异常时处理函数
callBack = new CallBack(ExceptionFilter);
SetUnhandledExceptionFilter(callBack);
此函数可让程序"美化"结束。
完整代码:
public partial class App : Application
{
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);
private delegate int CallBack(ref long a);
private CallBack callBack;
private System.Threading.Mutex mutex;
public App()
{
Startup += new System.Windows.StartupEventHandler(App_Startup);
}
private void App_Startup(object sender, System.Windows.StartupEventArgs e)
{
mutex = new System.Threading.Mutex(true, $"{System.Reflection.Assembly.GetEntryAssembly().GetName().Name} - 8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F", out bool ret);
if (!ret)
{
System.Windows.MessageBox.Show($"{System.Reflection.Assembly.GetEntryAssembly().GetName().Name} has already started up.",
"App_Startup",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
Environment.Exit(0);
return;
}
Log4net.Init(typeof(MainWindow));
// 设置UI线程发生异常时处理函数
System.Windows.Application.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
// 设置非UI线程发生异常时处理函数
AppDomain.CurrentDomain.UnhandledException += App_CurrentDomainUnhandledException;
// 设置非托管代码发生异常时处理函数
callBack = new CallBack(ExceptionFilter);
SetUnhandledExceptionFilter(callBack);
// 设置托管代码异步线程发生异常时处理函数
TaskScheduler.UnobservedTaskException += EventHandler_UnobservedTaskException;
}
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
Log4net.gLogger.Error("--<App_DispatcherUnhandledException>--" + e.Exception.ToString());
System.Windows.Forms.MessageBox.Show(e.Exception.ToString(),
"Error",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
e.Handled = true;
}
void App_CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Log4net.gLogger.Fatal("--<App_CurrentDomainUnhandledException>--" + e.ExceptionObject.ToString());
if (System.Windows.Forms.DialogResult.Yes
== System.Windows.Forms.MessageBox.Show(
"软件出现不可恢复错误,即将关闭。是否选择生成Dump文件以供开发人员分析问题?",
"Error", System.Windows.Forms.MessageBoxButtons.YesNo,
System.Windows.Forms.MessageBoxIcon.Error, System.Windows.Forms.MessageBoxDefaultButton.Button1))
{
WriteDump();
}
Environment.Exit(0);
}
private int ExceptionFilter(ref long a)
{
Log4net.gLogger.Fatal("--<ExceptionFilter>--" + Environment.StackTrace);
WriteDump();
return 1;
}
private void WriteDump()
{
Dump.WriteDumpFile();
}
}
对于一些问题,我们可以通过日志文件记录(我目前使用Log4net)。有时候日志不能完全帮助我们找到问题所在,这时dmp文件就可以帮助到我们。
internal class DumpWriter
{
public enum MiniDumpType
{
None = 0x00010000,
Normal = 0x00000000,
WithDataSegs = 0x00000001,
WithFullMemory = 0x00000002,
WithHandleData = 0x00000004,
FilterMemory = 0x00000008,
ScanMemory = 0x00000010,
WithUnloadedModules = 0x00000020,
WithIndirectlyReferencedMemory = 0x00000040,
FilterModulePaths = 0x00000080,
WithProcessThreadData = 0x00000100,
WithPrivateReadWriteMemory = 0x00000200,
WithoutOptionalData = 0x00000400,
WithFullMemoryInfo = 0x00000800,
WithThreadInfo = 0x00001000,
WithCodeSegs = 0x00002000
}
[DllImport("DbgHelp.dll")]
private static extern bool MiniDumpWriteDump(
IntPtr hProcess,
Int32 processId,
IntPtr fileHandle,
MiniDumpType dumpType,
ref MiniDumpExceptionInformation excepInfo,
IntPtr userInfo,
IntPtr extInfo);
[DllImport("DbgHelp.dll")]
private static extern bool MiniDumpWriteDump(
IntPtr hProcess,
Int32 processId,
IntPtr fileHandle,
MiniDumpType dumpType,
IntPtr excepParam,
IntPtr userInfo,
IntPtr extInfo);
[StructLayout(LayoutKind.Sequential, Pack = 4)]// Pack=4 is important! So it works also for x64!
private struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
[DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId();
private bool WriteDump(String dmpPath, MiniDumpType dmpType)
{
using (FileStream stream = new FileStream(dmpPath, FileMode.Create))
{
//取得进程信息
Process process = Process.GetCurrentProcess();
MiniDumpExceptionInformation mei = new MiniDumpExceptionInformation();
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = Marshal.GetExceptionPointers();
mei.ClientPointers = true;
bool res = false;
//如果不使用MiniDumpWriteDump重载函数
//当mei.ExceptioonPointers == IntPtr.Zero => 无法保存dmp文件
//且当mei.ClientPointers == false时程序直接崩溃(mei.ClientPointers == true程序不崩溃)
//
//以上测试信息硬件环境 cpu Pentium(R) Dual-Core CPU T4200 @ 2.00GHz
// vs2013update5
//在公司服务器上测试(64位系统、vs2013)不会出现上述情况
/*res = MiniDumpWriteDump(
process.Handle,
process.Id,
stream.SafeFileHandle.DangerousGetHandle(),
dmpType,
ref mei,
IntPtr.Zero,
IntPtr.Zero);*/
if (mei.ExceptionPointers == IntPtr.Zero)
{
res = MiniDumpWriteDump(
process.Handle,
process.Id,
stream.SafeFileHandle.DangerousGetHandle(),
dmpType,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
}
else
{
res = MiniDumpWriteDump(
process.Handle,
process.Id,
stream.SafeFileHandle.DangerousGetHandle(),
dmpType,
ref mei,
IntPtr.Zero,
IntPtr.Zero);
}
return res;
}
}
public DumpWriter()
{
FilePath = Environment.CurrentDirectory + @"\Dump";
if (!Directory.Exists(FilePath))
Directory.CreateDirectory(FilePath);
}
/// <summary>
/// 保存dmp文件路径
/// </summary>
public string FilePath { get; protected set; }
/// <summary>
/// 保存dmp文件名称(包括路径)
/// </summary>
public string FileName { get; protected set; }
/// <summary>
/// 写dmp文件
/// </summary>
/// <param name="dmpType">参数,不同参数保存内容不一样</param>
/// <returns></returns>
public bool WriteDumpFile(MiniDumpType dmpType)
{
FileName = string.Format("{0}\\{1}_{2}.dmp",
FilePath,
DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff"),
Process.GetCurrentProcess().ProcessName);
return WriteDump(FileName, dmpType);
}
}
好了,就写这么多吧。一般情况下,这些应该可以帮助我们解决大部分问题了。
wpf 单例模式和异常处理 (原发布 csdn 2017-04-12 20:34:12)的更多相关文章
- WPF 启动页面 (原发布 csdn 2017-06-26 19:26:01)
如果我写的有误,请及时与我联系,我立即改之以免继续误导他/她人. 如果您有好的想法或者建议,请随时与我联系. wpf软件启动时,加载启动页面.软件初始化完成之后关闭页面. App.xaml.cs代码 ...
- 关于“关于C#装箱的疑问”帖子的个人看法 (原发布csdn 2017年10月07日 10:21:10)
前言 昨天晚上闲着无事,就上csdn逛了一下,突然发现一个帖子很有意思,就点进去看了一下. 问题很精辟 int a = 1; object b=a; object c = b; c = 2; 为什么b ...
- c# Equal函数 and 运算符'==' (原发布 csdn 2017年10月15日 20:39:26)
1.==.!=.<.>.<= 和>= 运算符为比较运算符(comparison operator).C#语言规范5.0中文版中比较运算符的描述如下: 2.通用类型系统 3.值类 ...
- WPF DataGrid显示MySQL查询信息,且可删除、修改、插入 (原发布 csdn 2018-10-13 20:07:28)
1.入行好几年了,工作中使用数据库几率很小(传统行业).借着十一假期回家机会,学习下数据库. 2.初次了解数据库相关知识,如果本文有误,还望告知. 3.本文主要目的,记录下wpf界面显示数据库信息,且 ...
- WPF DispatcherTimer一些个人看法 (原发布 csdn 2017-04-25 19:12:22)
wpf中的DispatcherTimer基本用法,本文不在叙述.主要写一些不同的,来提醒自己不要再犯同样错误. 前几天写代码时发现.当在非UI线程创建DispatcherTimer实例时,程序无法进入 ...
- IEEE浮点表示 (原发布 csdn 2018-10-14 10:29:33)
目录 观察IEEE浮点表示 工作中遇到过整型转浮点型(union那种转换),碰到就看下书,过后就遗忘了.等过段时间又出现此现象,又重新拿起书本,这次记录了过程.然而一直等到今天才写出来,以防以后还用到 ...
- c# 类实例序列化反序列化json文件 (原发布 csdn 2017-10-01 20:02:12)
前言 前段时间使用了net.json保存对象数据.添加完成后,测试发现300多实例数据保存加载json文件,速度比原方式(BinaryFormatter)慢.但是功能加上后也懒再删掉代码了,索性就采用 ...
- C# 流介绍 (原发布 csdn 2017-09-15 23:37:52)
1.FileStream FileStream 详细介绍参考msdn 写数据: using (FileStream fs = new FileStream("File.FileStream& ...
- datalab (原发布 csdn 2018年09月21日 20:42:54)
首先声明datalab本人未完成,有4道题目没有做出来.本文博客记录下自己的解析,以便以后回忆.如果能帮助到你就更好了,如果觉得本文没啥技术含量,也望多多包涵. /* * bitAnd - x& ...
随机推荐
- HTML连载53-网易注册界面实战之content的头部、content注册信息
一. 这次完成了content部分的右边图片以及content的top部分的边角填充 <!DOCTYPE html> <html lang="en"> &l ...
- Linux下MySQL数据库的my.cnf配置文件,解决中文乱码问题
系统 CentOS 7.7 MySQL - 5.7.28文件放置目录:/etc/文件权限:644解决问题:存储中文数据乱码 # For advice on how to change settings ...
- CH-0304 IncDec Sequence
0304 IncDec Sequence 0x00「基本算法」例题 描述 给定一个长度为 n(n≤10^5 ) 的数列 {a_1,a_2,…,a_n},每次可以选择一个区间 [l,r],使下标在这个区 ...
- Python 从入门到进阶之路(五)
之前的文章我们简单介绍了一下 Python 的函数,本篇文章我们来看一下 Python 中的面向对象. Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是 ...
- 死磕 java线程系列之线程的生命周期
(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的. 常见的错 ...
- Git - Git版本库相关操作
创建Git版本库 如下命令实现在“E:\GitCode\01_TestGit”路径下,01_TestGit项目的Git版本库. $ cd E: #将当前目录转到E盘下 $ cd GitCode ...
- c# 异常精准定位
在日常项目开发中,异常抛出和捕获是再平常不过的事情.通过try-catch我们可以方便的捕获异常,同时通过查看异常堆栈我们能发现抛出异常代码的位置. 例如下面这段代码: using System; u ...
- 自学_DOM<五>
类库DOM DOM(document object medol)文档对象模型. DOM就是HTML页面的模型,将每个标签都做为一个对象,JavaScript通过调用DOM中的属性.方法就可以对网页中的 ...
- 单片机固件烧录器 Firmware Writer Android APP
GitHub地址 :https://github.com/WallBreakerX/mcu_firmware_writing_via_androidphone 用途 可在安卓手机上实现向单片机的h ...
- Thymeleaf常用语法:使用星号表达式
在处理模板时,一般情况都是使用变量表达式 ${...} 来显示变量,还可以使用选定对象表达式 *{...},它也称为星号表达式.如果在模板中先选定了对象,则需要使用星号表达式.Thymeleaf的内置 ...