我有一个在Firebird数据库中存储一些数据的应用程序。我正在使用嵌入式firebird服务器和EntityFramework,并且都可以很好地工作,但是当我通过窗体上的x按钮关闭我的应用程序时,出现了Windows系统消息“应用程序已停止工作”,并且我无法捕获此异常。我的应用程序中有一个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事件日志,并在其中找到error-event的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: http://stackoverflow.com/q/20959450/2504010 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嵌入式数据库的简单应用程序,以演示该错误。你可以在这里找到
该应用程序创建了一个firebird嵌入式数据库,并在后台线程(任务TPL)中连接到该数据库,并且在工作完成之后(_bgTask.Status == TaskStatus.RanToCompletion),请关闭该应用程序并获取错误。
在连接字符串中,已指定字符集并启用了连接池:
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
连接字符串参数(尽管我不知道这样做会带来什么后果)。
最后两个建议是解决方法。我可能会选择选项#1,因为它看起来最干净,它允许您保持连接池处于启用状态(这通常是一件好事),并指定所需的字符集。
还请注意,只有在连接了调试器的情况下运行应用程序,您才可能看到异常。在生产中,异常可能会保持沉默,并且完全不会被注意到。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句