考虑以下代码:
public class Class1
{
public static int c;
~Class1()
{
c++;
}
}
public class Class2
{
public static void Main()
{
{
var c1=new Class1();
//c1=null; // If this line is not commented out, at the Console.WriteLine call, it prints 1.
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Class1.c); // prints 0
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,即使main方法中的变量c1超出范围并且在GC.Collect()
调用时没有被任何其他对象进一步引用,为什么它没有在那里完成?
假设我有以下代码:
Sub TestRangeLoop()
Dim rng As Range
Set rng = Range("A1:A6")
''//Insert code to loop through rng here
End Sub
Run Code Online (Sandbox Code Playgroud)
我希望能够Range
为每个指定的单元格迭代一组对象rng
.从概念上讲,我想这样做:
For Each rngCell As Range in rng
''//Do something with rngCell
Next
Run Code Online (Sandbox Code Playgroud)
我知道我可以通过手动解析rng.Address
和构建Range
对象来解决这个问题,但我希望有一种更直接的方法,不涉及字符串解析.
我的数据网格视图中有10k行和15列.我想将此数据导出到excel表单o按钮.我已经尝试过以下代码.
private void btExport_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
app.Visible = true;
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
for(int i=1;i<dataGridView1.Columns.Count+1;i++)
{
worksheet.Cells[1, i] = dataGridView1.Columns[i-1].HeaderText;
}
for (int i=0; i < dataGridView1.Rows.Count-1 ; i++)
{
for(int j=0;j<dataGridView1.Columns.Count;j++)
{
if (dataGridView1.Rows[i].Cells[j].Value != null)
{
worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
else
{
worksheet.Cells[i + 2, j + 1] = "";
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这对我有用, …
编辑
另请参阅如何正确清理Excel互操作对象?.我最近遇到了这个问题,它提供了很多关于如何正确处理COM对象的问题的见解.绝对检查超出第一个(标记的)答案,因为其他答案超出了简单的"不要使用两个点"和" ReleaseComObject
用于每个com对象"的建议.
我首先重新审视了这个问题,因为我意识到尽管注册和处理所有COM对象非常彻底,但我的Excel实例仍然没有得到妥善处理.事实证明,有些方法可以创建完全不明显的COM对象(即,即使您从不使用两个点,也可以错过COM对象).此外,即使您是彻底的,如果您的项目增长超过一定的大小,错过COM对象的机会接近100%.当发生这种情况时,很难找到你错过的那个.上面链接的问题的答案提供了一些其他技术,以确保Excel实例肯定关闭.同时,我对我ComObjectManager
(下面)做了一个小的(但重要的)更新,以反映我从上面链接的问题中学到的东西.
原始问题
我已经看到了几个Marshal.ReleaseComObject()
与Excel Interop对象一起使用的例子(即来自命名空间Microsoft.Office.Interop.Excel的对象),但我已经看到它用于不同程度.
我想知道我是否可以逃避这样的事情:
var application = new ApplicationClass();
try
{
// do work with application, workbooks, worksheets, cells, etc.
}
finally
{
Marashal.ReleaseComObject(application)
}
Run Code Online (Sandbox Code Playgroud)
或者,如果我需要释放创建的每个对象,如此方法:
public void CreateExcelWorkbookWithSingleSheet()
{
var application = new ApplicationClass();
var workbook = application.Workbooks.Add(_missing);
var worksheets = workbook.Worksheets;
for (var worksheetIndex = 1; worksheetIndex < worksheets.Count; worksheetIndex++)
{
var worksheet = (WorksheetClass)worksheets[worksheetIndex];
worksheet.Delete();
Marshal.ReleaseComObject(worksheet);
}
workbook.SaveAs(
WorkbookPath, _missing, _missing, _missing, _missing, _missing,
XlSaveAsAccessMode.xlExclusive, _missing, …
Run Code Online (Sandbox Code Playgroud) 我遇到了Excel Interop的问题.
即使我重新发布实例,Excel.exe也不会关闭.
这是我的代码:
using xl = Microsoft.Office.Interop.Excel;
xl.Application excel = new xl.Application();
excel.Visible = true;
excel.ScreenUpdating = false;
if (wordFile.Contains(".csv") || wordFile.Contains(".xls"))
{
//typeExcel become a string of the document name
string typeExcel = wordFile.ToString();
xl.Workbook workbook = excel.Workbooks.Open(typeExcel,
oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing);
object outputFileName = null;
if (wordFile.Contains(".xls"))
{
outputFileName = wordFile.Replace(".xls", ".pdf");
}
else if (wordFile.Contains(".csv"))
{
outputFileName = wordFile.Replace(".csv", ".pdf");
}
workbook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, outputFileName,
XlFixedFormatQuality.xlQualityStandard, oMissing,
oMissing, …
Run Code Online (Sandbox Code Playgroud) 在我的公司中,发布Excel Interop Objects的常用方法是使用IDisposable,方法如下:
Public Sub Dispose() Implements IDisposable.Dispose
If Not bolDisposed Then
Finalize()
System.GC.SuppressFinalize(Me)
End If
End Sub
Protected Overrides Sub Finalize()
_xlApp = Nothing
bolDisposed = True
MyBase.Finalize()
End Sub
Run Code Online (Sandbox Code Playgroud)
在IDisposable
构造函数中以下列方式创建的位置:
Try
_xlApp = CType(GetObject(, "Excel.Application"), Excel.Application)
Catch e As Exception
_xlApp = CType(CreateObject("Excel.Application"), Excel.Application)
End Try
Run Code Online (Sandbox Code Playgroud)
并且客户端使用_xlApp
执行有关excel互操作对象的代码.
我们完全避免使用双点规则.现在我开始研究如何重新发布(Excel)互操作对象以及我发现的几乎所有关于它的讨论如何正确清理excel互操作对象或释放Excel对象主要使用Marshal.ReleaseComObject(),它们都没有使用IDisposable接口.
我的问题是:使用IDisposable Interace释放excel互操作对象有什么缺点吗?如果是这样,这些不利因素是什么.
我刚刚开始通过C#调整Excel,以便能够自动创建,并添加到Excel文件中.
我可以打开文件并更新其数据并浏览现有的工作表.我的问题是如何添加新表?
我试过了:
Excel.Worksheet newWorksheet;
newWorksheet = (Excel.Worksheet)excelApp.ThisWorkbook.Worksheets.Add(
Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Run Code Online (Sandbox Code Playgroud)
但我得到COM异常,我的谷歌搜索没有给我任何答案.
来自HRESULT的异常:0x800A03EC来源是:"Interop.Excel"
我希望有人能够让我摆脱困境.
我遇到了经典场景,当在.NET中创建Word COM对象时(通过Microsoft.Office.Interop.Word程序集),即使我正确关闭并释放对象,WinWord进程也不会退出.
我已经将其缩小到使用Word.Documents.Add()方法.我可以在没有问题的情况下以其他方式使用Word(打开文档,修改内容等),并在我告诉它时退出WinWord.exe.一旦我使用Add()方法(并且仅在添加模板时),该过程就会继续运行.
这是一个简单的例子,它可以重现这个问题:
Dim word As New Word.Application()
word.Visible = False
Dim documents As Word.Documents = word.Documents
Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath), NewTemplate:=False, DocumentType:=Word.WdNewDocumentType.wdNewBlankDocument, Visible:=False)
'' dispose objects
doc.Close()
While (Marshal.ReleaseComObject(doc) <> 0)
End While
doc = Nothing
While (Marshal.ReleaseComObject(documents) <> 0)
End While
documents = Nothing
word.Quit()
While (Marshal.ReleaseComObject(word) <> 0)
End While
word = Nothing
GC.Collect()
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在创建和正确处理对象,甚至采取额外的步骤来循环Marsha.ReleaseComObject,直到它返回正确的代码.在其他方面使用Word对象很好,只是那些讨厌的Documents.Add让我感到悲伤.是否有另一个在此过程中创建的对象需要引用和处理?我需要遵循另一个处理步骤吗?别的什么?非常感谢您的帮助 :)
Update:
我在处理步骤结束时尝试了GC.Collect,但仍然没有运气.
Update 2:
我已经将问题缩小到使用自定义模板.当我调用Documents.Add(...)时,我为新文档指定了一个自定义模板.如果我不这样做而是调用没有参数的Add(),那么问题就不会发生.
我想生成一个包含专有公式和其他知识产权的Excel工作簿.我很可能使用C#在Visual Studio 2010中生成此工作簿.
这些项目中的代码有多受保护?C#中的反射问题仍然适用于这些工作簿项目吗?如果是这样,是否有针对这些类型工作簿的混淆工具?
添加到这个问题 - 好的'ole VBA怎么样?如果我们要去VBA路线,有没有办法保护这些代码呢?
有时当我结束应用程序并尝试释放一些COM对象时,我会在调试器中收到警告:
RaceOnRCWCleanUp
被发现了
如果我编写一个使用COM对象的类,我是否需要实现IDisposable
并调用Marshal.FinalReleaseComObject
它们IDisposable.Dispose
才能正确释放它们?
如果Dispose
没有手动调用,我还需要在终结器中释放它们还是GC会自动释放它们?现在我打电话Dispose(false)
给终结者,但我想知道这是否正确.
我使用的COM对象也有一个类侦听的事件处理程序.显然,事件是在另一个线程上引发的,所以如果在处理类时触发它,如何正确处理呢?