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& ...
随机推荐
- 多个线程运行MR程序时hadoop出现的问题
夜间多个任务同时并行,总有几个随机性有任务失败,查看日志: cat -n ads_channel.log |grep "Caused by" Caused by: java.uti ...
- Java,该学什么?
本人大学学的是生物技术专业,毕业后入坑Java. 最近有人问我是如何转行的,需要学一些什么.我在网上看到一篇帖子,觉得写得很全.如果是我来写,可能还写不了这么全的.在此分享给网友. 2019秋招几个月 ...
- Linux 指令学习
查询java安装地址 which java ls -lrt /bin/java ls -lrt /etc/alternatives/java # 如果已经配好,则echo $JAVA_HOME 更改环 ...
- vue的provide和inject特性
由来 组件之间的通信可以通过props和$emit的方式进行通信,但是如果组件之间的关系非常复杂的话,通过以上的方式会很麻烦,并且程序会非常脆弱,没有建中性可言. 在==vue2.2.0 中新增pro ...
- Flask 教程 第六章:个人主页和头像
本文翻译自 The Flask Mega-Tutorial Part VI: Profile Page and Avatars 这是Flask Mega-Tutorial系列的第六部分,我将告诉你如何 ...
- MyBatis的结构和配置
概述 MyBatis将用户从JDBC的访问中解放出来,用户只需要定义需要操作的SQL语句,无须关注底层的JDBC操作,就可以面向对象的方式进行持久层操作.底层数据库连接的获取.数据访问的实现.事务控制 ...
- 【单条记录锁】select single for update
示例: DATA: wa_t001 type t001. select single for update * into wa_t001 from t001 where bukrs = '1000'. ...
- linux环境下卸载oracle 11g
1.停库[oracle@testdb ~]$ sqlplus / as sysdbaSQL> shutdown immediateDatabase closed.Database dismoun ...
- pymysql增删改查操作
表结构 CREATE TABLE `students` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFA ...
- Django-xadmin后台配置富文本编辑器(方法一)
1.https://github.com/twz915/DjangoUeditor3下载包,进入包文件夹,找到DjangoUeditor包拷贝到项目下,和xadmin同级目录 2.找到项目的setti ...