嵌入式服务器应用程序在退出后停止工作
Embedded server application has stopped working after exit
我有一个在 firebird 数据库中存储一些数据的应用程序。我正在使用嵌入式 firebird 服务器和 EntityFramework 并且一切正常,但是当我通过表单上的 x 按钮关闭我的应用程序时,我收到一条 windows 系统消息 "application has stopped working" 并且我无法捕捉这个例外。我的应用程序中有一个 UnhandledExceptionHandler :
// Add handler for UI thread exceptions
Application.ThreadException += new ThreadExceptionEventHandler(UIThreadException);
// Force all WinForms errors to go through handler
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//This handler is for catching non-UI thread exceptions
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
.....some other code..........
Application.Run(new MainForm());
但是这种异常一直没有被它捕捉到。所以我去了 windows 事件日志并在那里找到了这个 xml-错误事件视图:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Application Error" />
<EventID Qualifiers="0">1000</EventID>
<Level>2</Level>
<Task>100</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2017-03-14T23:06:25.000000000Z" />
<EventRecordID>36077</EventRecordID>
<Channel>Application</Channel>
<Computer>MYPC</Computer>
<Security />
</System>
- <EventData>
<Data>MyApp.exe</Data>
<Data>1.0.0.0</Data>
<Data>58c7a3f0</Data>
<Data>fbintl.DLL</Data>
<Data>2.5.5.26952</Data>
<Data>5644432f</Data>
<Data>c0000005</Data>
<Data>00004e9c</Data>
<Data>1d64</Data>
<Data>01d29d1797fb7f0d</Data>
<Data>G:\Programming\WorkSpace\C#\MyApp\bin\x86\Debug\MyApp.exe</Data>
<Data>G:\Programming\WorkSpace\C#\MyApp\bin\x86\Debug\FireBirdEmbeddedServer\intl\fbintl.DLL</Data>
<Data>d84a6ca6-090a-11e7-8151-005056c00008</Data>
</EventData>
</Event>
如您所见,fbintl.DLL 在应用已关闭时出现问题。那么我怎样才能得到关于这个问题的更详细的描述呢?
UPD
我使应用程序更短以检测我的问题的原因 - 现在只有此 EF 代码在应用程序关闭之前运行
public async Task GetAutoAnswerTemplate()
{
try
{
using (var db = new FirebirdDbContext(embeddedConnectionString)){
//Async or sync methods doesn't affect to my problem
AutoAnswerTemplate template = await dbContext.AutoAnswerTemplate.FirstOrDefaultAsync();
return template?.AutoAnswer_body;
}
}
catch (Exception ex)
{
throw new EmbeddedFbDataBaseTools.EmbeddedDbException(
"Error while getting auto answer template" + "\r\n" + ex.Message, ex);
}
}
FirebirdDbContext 所在的位置:
public class FirebirdDbContext : DbContext
{
public FirebirdDbContext(string connString)
: base(new FbConnection(connString), true)
{
//* The Entity initializer is bugged with Firebird embedded: so I didn't use default--->
// Database.SetInitializer<FirebirdDBContext>(new CreateDatabaseIfNotExists<FirebirdDBContext>());
Database.SetInitializer<FirebirdDbContext>(new MyCreateDatabaseIfNotExists());
}
public DbSet<AutoAnswerTemplate> AutoAnswerTemplate { get; set; }
public DbSet<User> User { get; set; }
}
class MyCreateDatabaseIfNotExists : IDatabaseInitializer<FirebirdDbContext>
{
public void InitializeDatabase(FirebirdDbContext context)
{
if (!context.Database.Exists())
{
context.Database.Create();
}
}
}
连接参数是
public static string GetEmbeddeddefaultConnectionString()
{
FbConnectionStringBuilder builder = new FbConnectionStringBuilder
{
ServerType = FbServerType.Embedded,
DataSource = "localhost",
Port = 3050,
Database = EmbeddedDbPath, //Path to embedded db
ClientLibrary = EmbeddedServerDllPath,
UserID = "SYSDBA",
Password = "masterkey",
Charset = "WIN1251",
Dialect = 3,
ConnectionLifeTime = 15,
Pooling = true,
MinPoolSize = 0,
MaxPoolSize = 50
};
return builder.ToString();
}
新更新 25.04.2017
我用 firebird 嵌入式数据库制作了一个简单的应用程序来演示错误。你能找到它here
该应用程序创建了一个 firebird 嵌入式数据库并在后台线程(任务 TPL)中连接到它,工作完成后(_bgTask.Status == TaskStatus.RanToCompletion)您关闭该应用程序并获取错误。
除了堆栈溢出异常和内存异常这两种情况外,您的异常处理应该有效。在这种情况下,行为应该是您描述的行为(系统消息"application has stopped working")。
关于堆栈溢出异常,当您在启用延迟加载的情况下序列化实体(json、xml、...)时,EF 经常发生。您是否在退出期间序列化实体?
如果这不是你的情况,你可以检查其他两件事:
- 你曾经分离过这两个事件处理程序吗?
- 您是否在异常处理程序中引发了异常?
调试您的代码有点棘手 _prepareAppTask = new TaskFactory().StartNew
会不时导致竞争条件,进而导致我在原始 post.
中描述的异常
当我尝试 运行 主线程中的数据库代码导致意外行为并让我想到它解决了问题时,你在幕后抛出和捕获异常并不明显。
除此之外,我在您的代码 中没有发现任何可能导致相关错误的关键问题。似乎是 firebird 本身或 EF 提供程序导致应用程序关闭问题。它与同步或异步代码无关——完全不像那样。我能够简单地 运行 在控制台应用程序中重现它。
应用程序在退出时崩溃并显示 错误模块名称:fbintl.DLL 仅当创建数据库连接并通过代码访问数据库时。 Faulting module what does this mean and why does this happen? 的答案让我认为问题出在 firebase 或 EF 提供程序上。
您是否尝试过其他方式连接到 firebase?
如果你只需要摆脱那个令人讨厌的异常,这里有一个对我有用的技巧:
private static void AppExit(object sender, EventArgs e)
{
...
// To ensure pending DB operations are processed. Not sure that's needed.
int timeout = 1000;
Thread.Sleep(timeout);
Process.GetCurrentProcess().Kill();
}
在进程退出之前终止进程可防止错误出现。
在您的连接字符串中,您指定了一个字符集并启用了连接池:
FbConnectionStringBuilder builder = new FbConnectionStringBuilder
{
…
Charset = "WIN1251",
…
Pooling = true,
…
};
这两个设置的组合似乎触发了错误;不是在您自己的代码中,而是在 FirebirdSQL 的代码中。到目前为止,我已经找到了三种方法来解决这个问题。您可以执行以下任一操作:
在您的应用程序终止之前调用静态 FbConnection.ClearAllPools()
方法(并启用连接池):
private static void AppExit(object sender, EventArgs e)
{
…
FbConnection.ClearAllPools();
}
通过设置Pooling = false
禁用连接池。
由于错误是在fbintl.dll
中触发的,这似乎是在处理字符集/国际化,您可以简单地省略Charset
连接字符串parameter(虽然我不知道这样会有什么后果)
最后两个建议是解决方法。我可能会选择选项 #1,因为它看起来最干净,允许您保持启用连接池(这通常是一件好事),并指定您需要的字符集。
另请注意,如果您 运行 您的应用程序附加了调试器,您可能只会看到异常。在生产中,异常可能会保持沉默并且完全不会被注意到。
我有一个在 firebird 数据库中存储一些数据的应用程序。我正在使用嵌入式 firebird 服务器和 EntityFramework 并且一切正常,但是当我通过表单上的 x 按钮关闭我的应用程序时,我收到一条 windows 系统消息 "application has stopped working" 并且我无法捕捉这个例外。我的应用程序中有一个 UnhandledExceptionHandler :
// Add handler for UI thread exceptions
Application.ThreadException += new ThreadExceptionEventHandler(UIThreadException);
// Force all WinForms errors to go through handler
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//This handler is for catching non-UI thread exceptions
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
.....some other code..........
Application.Run(new MainForm());
但是这种异常一直没有被它捕捉到。所以我去了 windows 事件日志并在那里找到了这个 xml-错误事件视图:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Application Error" />
<EventID Qualifiers="0">1000</EventID>
<Level>2</Level>
<Task>100</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2017-03-14T23:06:25.000000000Z" />
<EventRecordID>36077</EventRecordID>
<Channel>Application</Channel>
<Computer>MYPC</Computer>
<Security />
</System>
- <EventData>
<Data>MyApp.exe</Data>
<Data>1.0.0.0</Data>
<Data>58c7a3f0</Data>
<Data>fbintl.DLL</Data>
<Data>2.5.5.26952</Data>
<Data>5644432f</Data>
<Data>c0000005</Data>
<Data>00004e9c</Data>
<Data>1d64</Data>
<Data>01d29d1797fb7f0d</Data>
<Data>G:\Programming\WorkSpace\C#\MyApp\bin\x86\Debug\MyApp.exe</Data>
<Data>G:\Programming\WorkSpace\C#\MyApp\bin\x86\Debug\FireBirdEmbeddedServer\intl\fbintl.DLL</Data>
<Data>d84a6ca6-090a-11e7-8151-005056c00008</Data>
</EventData>
</Event>
如您所见,fbintl.DLL 在应用已关闭时出现问题。那么我怎样才能得到关于这个问题的更详细的描述呢?
UPD 我使应用程序更短以检测我的问题的原因 - 现在只有此 EF 代码在应用程序关闭之前运行
public async Task GetAutoAnswerTemplate()
{
try
{
using (var db = new FirebirdDbContext(embeddedConnectionString)){
//Async or sync methods doesn't affect to my problem
AutoAnswerTemplate template = await dbContext.AutoAnswerTemplate.FirstOrDefaultAsync();
return template?.AutoAnswer_body;
}
}
catch (Exception ex)
{
throw new EmbeddedFbDataBaseTools.EmbeddedDbException(
"Error while getting auto answer template" + "\r\n" + ex.Message, ex);
}
}
FirebirdDbContext 所在的位置:
public class FirebirdDbContext : DbContext
{
public FirebirdDbContext(string connString)
: base(new FbConnection(connString), true)
{
//* The Entity initializer is bugged with Firebird embedded: so I didn't use default--->
// Database.SetInitializer<FirebirdDBContext>(new CreateDatabaseIfNotExists<FirebirdDBContext>());
Database.SetInitializer<FirebirdDbContext>(new MyCreateDatabaseIfNotExists());
}
public DbSet<AutoAnswerTemplate> AutoAnswerTemplate { get; set; }
public DbSet<User> User { get; set; }
}
class MyCreateDatabaseIfNotExists : IDatabaseInitializer<FirebirdDbContext>
{
public void InitializeDatabase(FirebirdDbContext context)
{
if (!context.Database.Exists())
{
context.Database.Create();
}
}
}
连接参数是
public static string GetEmbeddeddefaultConnectionString()
{
FbConnectionStringBuilder builder = new FbConnectionStringBuilder
{
ServerType = FbServerType.Embedded,
DataSource = "localhost",
Port = 3050,
Database = EmbeddedDbPath, //Path to embedded db
ClientLibrary = EmbeddedServerDllPath,
UserID = "SYSDBA",
Password = "masterkey",
Charset = "WIN1251",
Dialect = 3,
ConnectionLifeTime = 15,
Pooling = true,
MinPoolSize = 0,
MaxPoolSize = 50
};
return builder.ToString();
}
新更新 25.04.2017
我用 firebird 嵌入式数据库制作了一个简单的应用程序来演示错误。你能找到它here
该应用程序创建了一个 firebird 嵌入式数据库并在后台线程(任务 TPL)中连接到它,工作完成后(_bgTask.Status == TaskStatus.RanToCompletion)您关闭该应用程序并获取错误。
除了堆栈溢出异常和内存异常这两种情况外,您的异常处理应该有效。在这种情况下,行为应该是您描述的行为(系统消息"application has stopped working")。
关于堆栈溢出异常,当您在启用延迟加载的情况下序列化实体(json、xml、...)时,EF 经常发生。您是否在退出期间序列化实体?
如果这不是你的情况,你可以检查其他两件事:
- 你曾经分离过这两个事件处理程序吗?
- 您是否在异常处理程序中引发了异常?
调试您的代码有点棘手 _prepareAppTask = new TaskFactory().StartNew
会不时导致竞争条件,进而导致我在原始 post.
当我尝试 运行 主线程中的数据库代码导致意外行为并让我想到它解决了问题时,你在幕后抛出和捕获异常并不明显。
除此之外,我在您的代码 中没有发现任何可能导致相关错误的关键问题。似乎是 firebird 本身或 EF 提供程序导致应用程序关闭问题。它与同步或异步代码无关——完全不像那样。我能够简单地 运行 在控制台应用程序中重现它。
应用程序在退出时崩溃并显示 错误模块名称:fbintl.DLL 仅当创建数据库连接并通过代码访问数据库时。 Faulting module what does this mean and why does this happen? 的答案让我认为问题出在 firebase 或 EF 提供程序上。
您是否尝试过其他方式连接到 firebase?
如果你只需要摆脱那个令人讨厌的异常,这里有一个对我有用的技巧:
private static void AppExit(object sender, EventArgs e)
{
...
// To ensure pending DB operations are processed. Not sure that's needed.
int timeout = 1000;
Thread.Sleep(timeout);
Process.GetCurrentProcess().Kill();
}
在进程退出之前终止进程可防止错误出现。
在您的连接字符串中,您指定了一个字符集并启用了连接池:
FbConnectionStringBuilder builder = new FbConnectionStringBuilder
{
…
Charset = "WIN1251",
…
Pooling = true,
…
};
这两个设置的组合似乎触发了错误;不是在您自己的代码中,而是在 FirebirdSQL 的代码中。到目前为止,我已经找到了三种方法来解决这个问题。您可以执行以下任一操作:
在您的应用程序终止之前调用静态
FbConnection.ClearAllPools()
方法(并启用连接池):private static void AppExit(object sender, EventArgs e) { … FbConnection.ClearAllPools(); }
通过设置
Pooling = false
禁用连接池。由于错误是在
fbintl.dll
中触发的,这似乎是在处理字符集/国际化,您可以简单地省略Charset
连接字符串parameter(虽然我不知道这样会有什么后果)
最后两个建议是解决方法。我可能会选择选项 #1,因为它看起来最干净,允许您保持启用连接池(这通常是一件好事),并指定您需要的字符集。
另请注意,如果您 运行 您的应用程序附加了调试器,您可能只会看到异常。在生产中,异常可能会保持沉默并且完全不会被注意到。