我在我正在重写的旧C#应用程序中使用MySQL .Net库。数据访问层相当过时,但我正在努力充分利用它。但现在我遇到了一些非常讨厌的线程问题。
我有一系列约20个用于处理报告的Select语句。它们需要大约5秒钟才能完成,我在Select语句运行时显示进度条。我通过简单的ThreadPool调用启动操作:
[后期编辑:由于我的用户界面中的错误,我将下面的方法称为两次 - 会发生这种情况 - 但这并没有使问题贬值,只是解释了为什么我的主题与每个人竞争其他。]
ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateChart));
我的DAL中的所有类都是Static,因为我认为这是提高性能的好方法(不必为每个小操作创建新的类实例)。
我所有的DAL类都使用相同的“root”DAL类来构建Connections:
public static class MySQLConnectionBuilder
{
private static MySqlConnectionStringBuilder ConnectionStringBuilder = new MySqlConnectionStringBuilder();
//I'm initializing the ConnectionStringBuilder with my server password & address.
public static MySqlConnection GetConnection ()
{
return new MySqlConnection(ConnectionStringBuilder.ConnectionString);
}
}
我的所有DAL类都具有与崩溃功能类似的功能。崩溃函数如下所示:
public static STDS.UserPresence.user_presenceDataTable GetPresence (int aUserID, DateTime aStart, DateTime aEnd)
{
ta.Connection = MySQLConnectionBuilder.GetConnection();
ds = ta.GetPresenceForUserBetweenDates(aUserID, aStart, aEnd);
ta.Connection.Close();
return ds;
}
想法?改进提示?如果我切换到更面向对象(实例驱动)的DAL,那么线程问题会消失吗?
答案 0 :(得分:1)
该行
ta.Connection.Close()
关闭最后分配给ta.Connection
的连接 - 并不总是在同一个线程中创建的连接。这可能会关闭当前正在另一个线程中运行查询的连接。
如果您想快速确定这是否正在发生,请使用类ta
中的[ThreadStatic]属性标记连接变量,指向:
[ThreadStatic]
private static MySqlConnection connection;
我不会将这种方法用于你的最终解决方案,因为它可能导致GC不收集它们。
一个简单的解决方案(对于 问题,我无法确定您的类是否存在其他多线程问题)是将连接作为参数添加到每个DAL方法中,允许您删除全球班Connection
:
public static STDS.UserPresence.user_presenceDataTable GetPresence (int aUserID, DateTime aStart, DateTime aEnd)
{
using (MySqlConnection connection = MySQLConnectionBuilder.GetConnection())
{
ds = ta.GetPresenceForUserBetweenDates(connection, aUserID, aStart, aEnd);
return ds;
}
}
线程问题永远不会消失 - 它们需要引起注意。如果您不确定发生了什么,请忘记轻微的性能提升(如果查询需要5秒,那么使用静态类的任何可能的性能增益都将低于1%)。