【问题标题】:(Another) .net Excel zombie issue(另一个).net Excel 僵尸问题
【发布时间】:2012-08-10 22:48:11
【问题描述】:

我有一个程序在后台留下一个 excel 僵尸进程的问题。我已经遵循了这里的所有建议和示例以及 MSDN 试图避免这种情况,但这让我发疯了。谁能发现导致僵尸进程发生的原因?

Imports System
Imports System.Collections
Imports System.IO
Imports Excel = Microsoft.Office.Interop.Excel

Private Sub LoadExcelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 处理 LoadExcelButton.Click

    Dim xlApp As New Excel.Application
    Dim xlBook As Excel.Workbook = Nothing 'instantiated to nothing to help try and avoid zombies
    Dim xlSheet As Excel.Worksheet = Nothing
    Dim STFRange As Excel.Range = Nothing

    Dim Name As String, Easting As Integer, Northing As Integer, tDSpa As Double, Type As String

    Dim NumberSTF As Integer, NumberProperties As Integer, i As Integer, ExcelPath As String

    ExcelPath = Me.ExcelPathTextBox.Text.ToString

    If File.Exists(ExcelPath) = False Then
        MessageBox.Show("Excel file does not exist, exiting.")
        Exit Sub
    End If

    Try

        xlApp.Visible = False

        xlBook = xlApp.Workbooks.Open(ExcelPath) ', , [ReadOnly]:=True

        xlSheet = xlBook.Sheets("STF")

        NumberSTF = xlSheet.UsedRange.Rows.Count - 1 '-1 to account for header
        NumberProperties = xlSheet.UsedRange.Columns.Count

        'create a new collection
        'http://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx
        Dim mySTFCollection As New STFCollection

        For i = 1 To NumberSTF 'rather than a for each loop which would require more excel ranges

            STFRange = xlSheet.Cells(i + 1, 1) '+1 on row to account for header
            Name = STFRange.Value.ToString

            STFRange = xlSheet.Cells(i + 1, 2)
            Easting = CInt(STFRange.Value)

            STFRange = xlSheet.Cells(i + 1, 3)
            Northing = CInt(STFRange.Value)

            STFRange = xlSheet.Cells(i + 1, 4)
            tDSpa = CDbl(STFRange.Value)

            STFRange = xlSheet.Cells(i + 1, 5)
            Type = STFRange.Value.ToString

            Dim objSTF As New STF(Name, Easting, Northing, tDSpa, Type)

            mySTFCollection.Add(objSTF)

        Next i

        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForPendingFinalizers()

        ReleaseObject(STFRange)
        STFRange = Nothing
        ReleaseObject(xlSheet)
        xlSheet = Nothing

        xlBook.Close(True, , )
        ReleaseObject(xlBook)
        xlBook = Nothing

        xlApp.Quit()
        ReleaseObject(xlApp)
        xlApp = Nothing

    Catch ex As Exception

        MessageBox.Show(ex.Message)

    End Try
End Sub

Public Sub ReleaseObject(ByVal obj As Object)

    Try
        Marshal.ReleaseComObject(obj)
        obj = Nothing
    Catch ex As Exception
        obj = Nothing
    Finally
        GC.Collect()
    End Try
End Sub

【问题讨论】:

  • 无法完成。您没有按照预期的方式使用 excel。 Excel 是一个桌面应用程序,互操作性是这种怪癖的好处。这就是为什么 MSDN 建议避免使用它,而不是因为他们是一群混蛋:p
  • 一定有可能,我不敢相信。我已经在从 ESRI ArcGIS 到 Excel 的 VBA 中完成了它,只是无法让它在 VB.net 上工作

标签: vb.net excel excel-interop


【解决方案1】:

您没有在 Excel 应用程序上调用 Close(),而是尝试过 Dispose()

您可能想尝试在代码的 finally 块中进行清理。

【讨论】:

  • 我所看到的没有可用的 dispose 方法
【解决方案2】:

第一件事第一件事

If File.Exists(ExcelPath) = False Then
    MessageBox.Show ("Excel file does not exist, exiting.")
    Exit Sub
End If

应该在Try - End Try 之外并且在您实例化您的 Excel 对象之前。如果路径不存在,您将指示代码退出子程序而不进行清理。

第二,最后使用GCcollect

这是我最喜欢的处理方式

Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
        '
        '~~> Rest of code
        '

        '~~> Close workbook and quit Excel
        xlWb.Close (False)
        xlApp.Quit()

        '~~> Clean Up
        releaseObject (xlApp)
        releaseObject (xlWb)
End Sub

Private Sub releaseObject(ByVal obj As Object)
    Try
        System.Runtime.InteropServices.Marshal.ReleaseComObject (obj)
        obj = Nothing
    Catch ex As Exception
        obj = Nothing
    Finally
        GC.Collect()
    End Try
End Sub

如果您热衷于 VB.net 的 Excel 自动化,那么我建议您通过 link

跟进

使用此代码。

Private Sub LoadExcelButton_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim Name As String = "", Type As String = "", ExcelPath As String = ""
    Dim Easting As Integer = 0, Northing As Integer = 0
    Dim NumberSTF As Integer = 0, NumberProperties As Integer = 0, i As Integer = 0
    Dim tDSpa As Double = 0

    ExcelPath = Me.ExcelPathTextBox.Text.ToString

    If File.Exists(ExcelPath) = False Then
        MessageBox.Show("Excel file does not exist, exiting.")
        Exit Sub
    End If

    Dim xlApp As New Excel.Application
    Dim xlBook As Excel.Workbook = Nothing
    Dim xlSheet As Excel.Worksheet = Nothing
    Dim STFRange As Excel.Range = Nothing

    xlApp.Visible = True

    xlBook = xlApp.Workbooks.Open(ExcelPath)

    xlSheet = xlBook.Sheets("STF")

    NumberSTF = xlSheet.UsedRange.Rows.Count - 1
    NumberProperties = xlSheet.UsedRange.Columns.Count

    'create a new collection
    'http://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx
    Dim mySTFCollection As New STFCollection

    For i = 1 To NumberSTF

        STFRange = xlSheet.Cells(i + 1, 1)
        Name = STFRange.Value.ToString

        STFRange = xlSheet.Cells(i + 1, 2)
        Easting = CInt(STFRange.Value)

        STFRange = xlSheet.Cells(i + 1, 3)
        Northing = CInt(STFRange.Value)

        STFRange = xlSheet.Cells(i + 1, 4)
        tDSpa = CDbl(STFRange.Value)

        STFRange = xlSheet.Cells(i + 1, 5)
        Type = STFRange.Value.ToString

        Dim objSTF As New STF(Name, Easting, Northing, tDSpa, Type)

        mySTFCollection.Add(objSTF)

    Next i

    '~~> Close the File
    xlBook.Close(False)

    '~~> Quit the Excel Application
    xlApp.Quit()

    '~~> Clean Up
    releaseObject(xlSheet)
    releaseObject(xlBook)
    releaseObject(xlApp)
End Sub

'~~> Release the objects
Private Sub releaseObject(ByVal obj As Object)
    Try
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
        obj = Nothing
    Catch ex As Exception
        obj = Nothing
    Finally
        GC.Collect()
    End Try
End Sub

【讨论】:

  • 谢谢,我明天试试
  • 好的,我试过了,但没什么区别,我的记忆里还有一个僵尸。
  • 您能否更新您现在在问题中使用的确切代码
  • 好的,上面更新了,我不知道如何通过评论添加它。谢谢你
  • 啊,我明白你做了什么。我正在笔记本电脑上安装东西。将在几个小时内更新代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多