VB.NET调用SQLite后二次点击生成邮件按钮程序卡顿无响应求助
解决VB.NET程序第二次点击邮件按钮挂起的问题
嘿,我看了你的代码,问题大概率出在资源没有被正确释放上——第一次运行时资源还能正常分配,但第二次操作时,之前的资源没释放干净,导致程序卡住了。咱们一步步来修复:
1. 修复SQLite连接的资源释放问题
你的GetAddresses函数里,SQLite连接是手动打开和关闭的,虽然最后设了myConnection = Nothing,但这种方式不如用Using块可靠——Using会自动帮你释放资源,哪怕中间抛出异常也能确保连接被关闭,不会因为残留连接导致后续操作挂起。
修改后的GetAddresses函数:
Function GetAddresses(table As String) As String ' 用Path.Combine避免路径拼接出错 Dim dbPath As String = Path.Combine(Directory.GetCurrentDirectory(), "test.db") Dim connectionString As String = $"Data Source={dbPath};" ' 用StringBuilder优化字符串拼接效率(避免频繁创建字符串对象) Dim resultString As New StringBuilder() ' 把SQLiteConnection放进Using块,自动释放资源 Using myConnection As New SQLiteConnection(connectionString) myConnection.Open() ' 用参数化查询避免SQL注入风险,同时更安全 Dim sSQL As String = "SELECT * FROM @TableName;" Using cmd As New SQLiteCommand(sSQL, myConnection) cmd.Parameters.AddWithValue("@TableName", table) Using rdr As SQLiteDataReader = cmd.ExecuteReader() While rdr.Read() resultString.Append($"{rdr.GetInt32(0)} - {rdr.GetString(1)}") End While End Using End Using End Using ' 这里会自动关闭并释放连接,无需手动Close Return resultString.ToString() End Function
2. 修复MAPI对象的COM资源清理问题
你在CreateEmail里虽然把mapi = Nothing,但My.MAPI是封装Outlook COM组件的类,单纯赋值为Nothing没法彻底释放COM资源——第二次创建实例时,前一次的COM资源没释放,就会导致程序卡住。
方案一:如果MAPI类实现了IDisposable接口
直接把MAPI放进Using块,自动调用Dispose释放资源:
Sub CreateEmail() ' 用Using包裹MAPI实例,自动释放资源 Using mapi As New My.MAPI() Dim EmailAddresses As New StringBuilder() ' 获取选中的邮箱地址 For Each c As Control In GroupBox2.Controls If TypeOf c Is CheckBox Then Dim cb As CheckBox = DirectCast(c, CheckBox) If cb.Checked Then EmailAddresses.Append(GetAddresses(cb.Text)) End If End If Next ' 添加附件 For Each rowView As DataRowView In ListBox1.Items Dim value As String = rowView("Value").ToString() mapi.AddAttachment(value) Next mapi.AddRecipientTo(EmailAddresses.ToString()) mapi.SendMailPopup("Subject", "body text") End Using ' 自动释放MAPI的COM资源 End Sub
方案二:如果MAPI类没实现IDisposable
手动强制释放COM资源:
Sub CreateEmail() Dim mapi As New My.MAPI() Dim EmailAddresses As New StringBuilder() ' 获取选中的邮箱地址 For Each c As Control In GroupBox2.Controls If TypeOf c Is CheckBox Then Dim cb As CheckBox = DirectCast(c, CheckBox) If cb.Checked Then EmailAddresses.Append(GetAddresses(cb.Text)) End If End If Next ' 添加附件 For Each rowView As DataRowView In ListBox1.Items Dim value As String = rowView("Value").ToString() mapi.AddAttachment(value) Next mapi.AddRecipientTo(EmailAddresses.ToString()) mapi.SendMailPopup("Subject", "body text") ' 强制释放COM资源 System.Runtime.InteropServices.Marshal.ReleaseComObject(mapi) mapi = Nothing GC.Collect() GC.WaitForPendingFinalizers() End Sub
3. 额外排查点
- 检查Outlook是否在第二次点击时处于异常状态(比如前一个邮件窗口未正常关闭、Outlook被锁定)
- 确保
My.MAPI的SendMailPopup方法里没有残留未释放的Outlook COM对象
按照上面的修改,应该能解决第二次点击挂起的问题——核心就是确保所有资源(数据库连接、COM对象)都被彻底释放,不会被后续操作占用。
内容的提问来源于stack exchange,提问作者Sonu Singh
相关产品推荐
相关产品推荐

