簡體   English   中英

多次處置對象

[英]Disposing of object multiple times

我有以下代碼,它使用流來打開和修改Open XML文檔,然后保存該流的新二進制表示:

MemoryStream stream = null;
try
{
    stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))
    {
        OfficeDocument.ModifyDocument(document);
        this.SetBinaryRepresentation(stream.ToArray());
        stream = null;
    }
}
finally
{
    if (stream != null)
    {
        stream.Dispose();
    }
}

我最初使用了兩個使用塊(一個用於MemoryStream,第二個用於WordprocessingDocument),但收到警告CA2202:“對象'流'可以在方法中多次處理...”根據MSDN文章 ,我修改了上面的代碼(將外部使用轉換為試用),但我仍然收到此警告。

我不確定如何構造此方法以確保在流上只調用一次Dispose。 我不想簡單地抑制此警告,因為MSDN文章聲明您不應該依賴Dispose多次安全地調用。

多次處理物體應始終是安全的。 Dispose文檔

如果多次調用對象的Dispose方法,則該對象必須忽略第一個之后的所有調用。 如果多次調用Dispose方法,則該對象不得拋出異常。

話雖這么說,使用聲明絕對是這里的方式。 您收到該方法的唯一原因是,如果您明確處置了不需要的對象,因為using語句應該始終只處理一次對象。

如果在將流設置為空之前在使用塊中拋出異常,則流仍可被丟棄兩次。 嘗試這個:

MemoryStream stream = null;
MemoryStream streamToDispose = null;
try
{
    streamToDispose = stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))
    {
        streamToDispose = null;
        OfficeDocument.ModifyDocument(document);
        this.SetBinaryRepresentation(stream.ToArray());
    }
}
finally
{
    if (streamToDispose != null)
    {
        streamToDispose.Dispose();
    }
}

MSDN文章中的示例不適合您的原因是它們在進入using塊時將流設置為null,而您使用using塊中的流並將流設置為null。 如果在stream = null語句之前拋出異常,則在退出using塊時將丟棄stream ,然后在finally塊中再次處理。

不幸的是,由於您需要在document更新之后訪問您的流,我沒有看到一種干凈的方法來使用他們在您的using語句中設置stream = null的示例來避免多次Dispose()調用。 另一種方法是你可以在try塊之外聲明streamdocument ,然后在finally中清除它們,如下所示:

MemoryStream stream = null;
WordprocessingDocument document = null;
try
{
    stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    document = WordprocessingDocument.Open(stream, true));

    OfficeDocument.ModifyDocument(document);
    this.SetBinaryRepresentation(stream.ToArray()); 
}
finally
{
    if( document != null)
    {
        document.Dispose();
    }
    // Catch the case where an error occurred before document was defined.
    else
    {
        stream.Dispose();
    }
}

using語句處理對象 - 所以基本上你調用dispose兩次

當您的代碼在WordProcessingDocument周圍離開使用塊時,它將調用dispose。

using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))

由於WordProcessingDocument需要的實例stream在其構造,它會調用該流實例處理時WordProcessingDocument.Dispose被調用。 然后輸入您調用stream.Dispose()的finally塊 - 您現在已在流實例上調用兩次Dispose()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM