如何捕捉异常? 本帖最后由 jshzp 于 2012-01-14 10:36:22 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 try { test(); } catch (Exception ex) { this.textBox1.Text = ex.ToString(); } 我给了个错误的服务器IP,运行调试,Intellitrace中断后的截图,显示有多次异常,但是程序并没有catch到,2楼的代码也不行。继续求教,谢谢! 那就说明不是try里面的代码发生了异常,可能是在他之前就发生异常了.可以再整个函数里加一个try...catch来捕获. 嗯,确实是另外的代码引发的异常try { con.Open(); } catch (Exception e) {//设置断点 if ((e.Message.ToString()).Contains("provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接")) return null; }但是调试发现,在程序运行到所设置的断点时,Intellitrace显示已经出现了很多次(大约十次)3楼所示的异常,这些异常都是con.Open()语句已发的。怎样才能及时捕获到异常呢?我想在第一次引发时就能捕获到。谢谢! try{}catch{}fillny{} try 是抛出异常。真真的能告诉你什么出问题的是Exception类 throw new ;这边可以自定义异常 try{ con = new SqlConnection("data source=" + validServerIP + ";uid=sa;Password=a8bak66;Initial Catalog=jsdb;Timeout=60 ");}catch(Exception e){//这里设置断点 string errorStr=e.Message;//这里就是异常信息了、} 举个例子,如果你的代码是从form的事件开始的,那这个事件就是你的应用程序的一个边界所有的代码片段的起始点都是应用程序边界如果你真的不知道如何在合适的位置捕获异常,那就只在Main函数捕获异常,调用e.StackTrace.ToString()可以列印出完整的异常堆栈,程序员就可以知道完整的异常传导路径try { //code }catch (Exception e) { Console.WriteLine(e.StackTrace.ToString()); }finally { //clean-up } 少了Main函数体:static void Main(string[] args) { try { //code } catch (Exception e) { Console.WriteLine(e.StackTrace.ToString()); } finally { //clean-up } } 进一步的,你可以把e.StackTrace解析一下,漂漂亮亮的打印出来,就象这样:尽管,打印e.StackTrace算是最简陋的异常处理机制了,但是,仅仅是报告完整的异常传导路径,就已经能极大的降低debug的次数了 感谢你的耐心解释。这样做,不仅可以处理我的bug,也应该可以处理其它的,有通用性,很有意义。暂不结贴,希望更多的人能看到。 但是我目前的问题是,当3楼所示的异常出现大约十次以后,我的代码才能catch到(大约半分钟)。我想在第一次引发异常时就能catch到,以便程序做出及时的处理。不知道是否。net对这种和网络有关的异常,需要连续引发某个特定的次数后,才向用户程序抛出?如果我的猜测是对的,那么还有办法吗?望继续指教,谢谢! 这样catch不到第一次引发的异常!我使用的代码见5楼。 楼主,你所纠结的现象,是由于你不恰当地捕获并"隐瞒",才会导致的你可以尝试清除所有catch,只在main函数catch,你会看到你想要的结果 代码改成下面的样子: /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } catch { } }调试结果一样。当程序运行到catch语句时,通过IntelliTrace可以看到,已经引发了近二十次相同的异常。鼠标双击这些IntelliTrace事件“已引发”光标都是指向了5楼代码中的语句con.Open()。望继续指教,谢谢! 你倒是报告异常啊catch (Exception e) { Console.WriteLine(e.StackTrace.ToString()); } 先感谢microtry的耐心!代码改成下列的样子:static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } catch (Exception e) { Console.WriteLine(e.StackTrace.ToString());//断点 } } }当catch到异常后,及运行到断点处,e.StackTrace.ToString()的内容如下:在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity) 在 System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)在 System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) 在 System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) 在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) 在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) 在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) 在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)在 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 在 System.Data.SqlClient.SqlConnection.Open() 在 Service.SqlDB.SqlOpen() 位置 E:\hzp\dllService\dllService\dllService\SqlDB.cs:行号 63 在 Service.SqlDB.ExecTable(String sql) 位置 E:\hzp\dllService\dllService\dllService\SqlDB.cs:行号 90 在 WindowsFormsApplication49.Form1.Form1_Load(Object sender, EventArgs e) 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Form1.cs:行号 33 在 System.Windows.Forms.Form.OnLoad(EventArgs e) 在 System.Windows.Forms.Form.OnCreateControl() 在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) 在 System.Windows.Forms.Control.CreateControl() 在 System.Windows.Forms.Control.WmShowWindow(Message& m) 在 System.Windows.Forms.Control.WndProc(Message& m) 在 System.Windows.Forms.ScrollableControl.WndProc(Message& m) 在 System.Windows.Forms.Form.WmShowWindow(Message& m) 在 System.Windows.Forms.Form.WndProc(Message& m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 在 System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow) 在 System.Windows.Forms.Control.SetVisibleCore(Boolean value) 在 System.Windows.Forms.Form.SetVisibleCore(Boolean value) 在 System.Windows.Forms.Control.Show() 在 WindowsFormsApplication49.Form1..ctor() 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Form1.cs:行号 19 在 WindowsFormsApplication49.Program.Main() 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Program.cs:行号 20可以看出异常的传导过程,其中导致异常的我的代码是SqlDB.cs:行号 63 ,对应的语句是con.Open();但是当程序运行到断点处时,大约已经运行了约半分钟,(如果服务器IP设置正确,应该是不到一秒),而在这半分钟里,通过IntelliTrace可以看到,已经引发了近二十次相同的异常了(如3楼所示)。为什么我的代码不能在第一次引发异常时就catch到呢?这是否是.net的策略,即多次引发后才抛向用户代码?确实很纠结这个问题,因为我想让程序能反应得更快些 "不知道是否。net对这种和网络有关的异常,需要连续引发某个特定的次数后,才向用户程序抛出?"想想也是有理由的,因为我们经常有这样的经验,网络偶尔不正常,但是仅需重试后,就OK了。所以SqlClient类的方法(例如SqlClient.SqlConnection.Open())引发异常后,并不是立即抛出给用户代码,而是再次尝试运行,如果连续多次都不正常,才断定是故障而放弃,才抛出异常,这时才能被代码catch到。根据我的经验,当做FTP从服务器上传下载时,如果引发异常,那么在代码能够catch到之前,必定是已经引发了6次了!以前没有在意这个事情,这些天在考虑改进程序,以适应网络不稳定性,所以遇到了帖子中的问题。如果我猜测的正确,那么还有办法吗?望高手继续指教,谢谢! 楼主需要捕获具体的异常就算补货所有异常也应该是用Exception 你咋知道不是因为一个异常引起的20个多个异常呢?因为使用try catch 嵌套的话是可以把所有异常最终抛到最外层的。也就是说你0楼的代码 try中 导致了20多个内部错误try{ con = new SqlConnection("data source=" + validServerIP + ";uid=sa;Password=a8bak66;Initial Catalog=jsdb;Timeout=60 ");}catch{//这里设置断点} 网络连接都有超时时间,在没有超时之前会一直尝试连接。Connection.Open方法默认超时N秒,IP错误、端口未打开之类的非网速故障总是很快返回结果,因此在尝试多次连接后才会到达超时时间,抛出异常。 惭愧,IntelliTrace一直不知道干嘛的,只知道他会把我的硬盘吃光。所以一般都禁用了 应该是如intotheland在31、32楼所说的。net并没有把所有的网络异常都及时地抛给用户,而是先尝试N次,确认故障后,再抛出。如此,用户是没有办法及时处理了我这里说的处理不是指程序界面响应,而是及时更换到备用服务器,所以和多线程之类的无关。 你把连接初始化放在Form1.Form1_Load里面了? 在不在FormLoad里面,有什么影响呢?嗯,我是在线程中干的。 到今天位置,问题并没有解决。只是有了更清楚的认识,其实就是intotheland解释的那样。或许,就是微软为对付糟糕的网络状况的策略而已。 有没有谁用过可以自己生成数据库表实体代码的工具或者有源码? C# 怎样才能让鼠标按住控件并左右移动控件 如何只读取groupBox1中的label,不读其他的如textBox asp.net怎么样得到页面滚动条的位置 各位大虾赐教小妹一个疑问吧,急!急!在线等,不胜感激!!我会给大家打分的 怎样对Excel中的数据进行整列修改? 请教:水晶报表预览时显示正常,打印出来是乱码 c#如何对excel进行直接操作 送分题!大家快来! 简单问题快来拿分!! 关于腾讯QQ超链接里面的摘要 这个读取word的时候 没有样式,求教了。
{
test();
}
catch (Exception ex)
{
this.textBox1.Text = ex.ToString();
}
我给了个错误的服务器IP,运行调试,Intellitrace中断后的截图,显示有多次异常,但是程序并没有catch到,2楼的代码也不行。
继续求教,谢谢!
try
{
con.Open();
}
catch (Exception e)
{//设置断点
if ((e.Message.ToString()).Contains("provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接")) return null;
}
但是调试发现,在程序运行到所设置的断点时,Intellitrace显示已经出现了很多次(大约十次)3楼所示的异常,这些异常都是con.Open()语句已发的。
怎样才能及时捕获到异常呢?我想在第一次引发时就能捕获到。谢谢!
try
{
}
catch
{
}
fillny
{
}
throw new ;这边可以自定义异常
{
con = new SqlConnection("data source=" + validServerIP + ";uid=sa;Password=a8bak66;Initial Catalog=jsdb;Timeout=60 ");
}
catch(Exception e)
{//这里设置断点
string errorStr=e.Message;//这里就是异常信息了、
}
所有的代码片段的起始点都是应用程序边界如果你真的不知道如何在合适的位置捕获异常,那就只在Main函数捕获异常,
调用e.StackTrace.ToString()可以列印出完整的异常堆栈,
程序员就可以知道完整的异常传导路径try {
//code
}
catch (Exception e) {
Console.WriteLine(e.StackTrace.ToString());
}
finally {
//clean-up
}
static void Main(string[] args) {
try {
//code
}
catch (Exception e) {
Console.WriteLine(e.StackTrace.ToString());
}
finally {
//clean-up
}
}
你可以把e.StackTrace解析一下,漂漂亮亮的打印出来,就象这样:
尽管,打印e.StackTrace算是最简陋的异常处理机制了,
但是,仅仅是报告完整的异常传导路径,就已经能极大的降低debug的次数了
这样做,不仅可以处理我的bug,也应该可以处理其它的,有通用性,很有意义。暂不结贴,希望更多的人能看到。
如果我的猜测是对的,那么还有办法吗?望继续指教,谢谢!
你可以尝试清除所有catch,只在main函数catch,你会看到你想要的结果
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
catch
{ }
}调试结果一样。当程序运行到catch语句时,通过IntelliTrace可以看到,已经引发了近二十次相同的异常。鼠标双击这些IntelliTrace事件“已引发”光标都是指向了5楼代码中的语句con.Open()。
望继续指教,谢谢!
catch (Exception e) {
Console.WriteLine(e.StackTrace.ToString());
}
代码改成下列的样子:
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace.ToString());//断点
}
}
}
当catch到异常后,及运行到断点处,e.StackTrace.ToString()的内容如下:
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
在 System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity)
在 System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
在 System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
在 System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
在 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
在 System.Data.SqlClient.SqlConnection.Open()
在 Service.SqlDB.SqlOpen() 位置 E:\hzp\dllService\dllService\dllService\SqlDB.cs:行号 63
在 Service.SqlDB.ExecTable(String sql) 位置 E:\hzp\dllService\dllService\dllService\SqlDB.cs:行号 90
在 WindowsFormsApplication49.Form1.Form1_Load(Object sender, EventArgs e) 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Form1.cs:行号 33
在 System.Windows.Forms.Form.OnLoad(EventArgs e)
在 System.Windows.Forms.Form.OnCreateControl()
在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
在 System.Windows.Forms.Control.CreateControl()
在 System.Windows.Forms.Control.WmShowWindow(Message& m)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
在 System.Windows.Forms.Form.WmShowWindow(Message& m)
在 System.Windows.Forms.Form.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
在 System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
在 System.Windows.Forms.Control.SetVisibleCore(Boolean value)
在 System.Windows.Forms.Form.SetVisibleCore(Boolean value)
在 System.Windows.Forms.Control.Show()
在 WindowsFormsApplication49.Form1..ctor() 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Form1.cs:行号 19
在 WindowsFormsApplication49.Program.Main() 位置 E:\work\WindowsFormsApplication49\WindowsFormsApplication49\Program.cs:行号 20
可以看出异常的传导过程,其中导致异常的我的代码是SqlDB.cs:行号 63 ,对应的语句是con.Open();但是当程序运行到断点处时,大约已经运行了约半分钟,(如果服务器IP设置正确,应该是不到一秒),而在这半分钟里,通过IntelliTrace可以看到,已经引发了近二十次相同的异常了(如3楼所示)。
为什么我的代码不能在第一次引发异常时就catch到呢?这是否是.net的策略,即多次引发后才抛向用户代码?
确实很纠结这个问题,因为我想让程序能反应得更快些
"
想想也是有理由的,因为我们经常有这样的经验,网络偶尔不正常,但是仅需重试后,就OK了。所以SqlClient类的方法(例如SqlClient.SqlConnection.Open())引发异常后,并不是立即抛出给用户代码,而是再次尝试运行,如果连续多次都不正常,才断定是故障而放弃,才抛出异常,这时才能被代码catch到。
根据我的经验,当做FTP从服务器上传下载时,如果引发异常,那么在代码能够catch到之前,必定是已经引发了6次了!以前没有在意这个事情,这些天在考虑改进程序,以适应网络不稳定性,所以遇到了帖子中的问题。
如果我猜测的正确,那么还有办法吗?望高手继续指教,谢谢!
因为使用try catch 嵌套的话是可以把所有异常最终抛到最外层的。
也就是说
你0楼的代码 try中 导致了20多个内部错误try
{
con = new SqlConnection("data source=" + validServerIP + ";uid=sa;Password=a8bak66;Initial Catalog=jsdb;Timeout=60 ");
}
catch
{//这里设置断点
}
Connection.Open方法默认超时N秒,IP错误、端口未打开之类的非网速故障总是很快返回结果,因此在尝试多次连接后才会到达超时时间,抛出异常。
如此,用户是没有办法及时处理了
我这里说的处理不是指程序界面响应,而是及时更换到备用服务器,所以和多线程之类的无关。