2010-10-13 65 views
1

我打開FileStreamFileMode.OpenFileAccess.Read。不久之後,我調用一個函數來處理文件的內容。我使用Invoke撥打電話,因爲該電話來自Thread,該功能必須將結果放在Form上。該函數接受任何類型的流(我也稱它爲MemoryStream也沒有問題),並使用XmlTextReader讀取FileStream中的XML,但在罕見情況下,由於未知原因,即使第一個Read()也會拋出ObjectDisposedException,並且流的CanRead屬性返回如果該流已關閉,則爲false。新的FileStream已經關閉/處理?

ThreadFileStream是本地using變量,所以我不認爲其他線程應該可以關閉它,我不關閉,直到返回Invoke。沒有Exceptions拋出所以該文件是有限的(因爲沒有FileNotFoundException),應該正確訪問(因爲沒有UnauthorizedAccessExceptionIOException)。

我的FileStream在打開後有時還會關閉?

(也許沒關係,我現在運行我在Windows CE 5設備上的代碼Compact Framework的3.5和我無法重現我的XP桌面PC上相同的行爲呢。)

編輯: 我知道,這個調用是醜陋的,但這不能是一個失敗的理由,可以嗎? (並且在大多數情況下它根本不會失敗。)

//the code in the thread 
//... 
using (FileStream fs = File.Open(assemblyPath + "\\white.xml", FileMode.Open, FileAccess.Read)) 
{ 
    mainForm.Instance.Invoke(new DataHandler(mainForm.Instance.handleData), new object[] { fs }); 
} 
//... 

//and the handler 
public void handleData(Stream stream) 
{ 
    infoPanel.SuspendLayout(); 
    try 
    { 
     using (XmlTextReader xml = new XmlTextReader(stream)) 
     { 
      //it doesn't matter what is here 
     } 
    } 
    catch{} 
} 
+0

聽起來好像是打開的文件已經關閉了流的其他線程有機會到之前的線程在...上下功夫。很可能你應該在打開它的線程中完全處理該文件,並使用'Invoke'來傳遞整個字符串或進度的增量通知。但是不要將整個Stream傳遞給'Invoke'。你可以發佈你的代碼是打開文件,也是'Invoke'的處理程序? – 2010-10-13 13:55:48

回答

1

我可以想到的一個原因是:工作線程被中止。這將使用語句運行由生成的finally塊並關閉文件。如何中止是次要問題。該線程的IsBackground屬性是否設置爲true?該程序是否在其他地方發生未處理的異常並關閉?只是猜測當然。

1

當然,這是預期的行爲。您調用Invoke,將調用整理到另一個線程。調用線程繼續運行,並使用塊退出,在流上調用Dispose。此Dispose在完成之前(也可能在開始之前)在UI線程中使用流進行。這些行動的確切時間將取決於處理器負載和其他一些因素,但這肯定是不安全的。

要麼不把流放在使用塊中,要麼讓線程執行讀取操作並將結果通過Invoke傳遞給UI。

編輯

正如漢斯在評論中指出,上述的解釋應該是一個BeginInvoke的調用,調用下面PostMessage的。另一方面,調用使用SendMessage。兩者都可能使用一些WM_COPYDATA shenanigans(我沒有看過)來編組數據。

Invoke調用應該正在執行您發佈的整個處理程序,儘管您看到的行爲指示了其他情況。從您發佈的代碼中,我們無法確定什麼是關閉流。

我仍然會重構你在這裏完成的工作,因爲現在你正在用讀取器操作綁定UI和工作線程。我會在工作線程中完成讀取工作,然後將結果傳遞給UI。這會降低讀者工作導致用戶界面不穩定的可能性,並會消除在您閱讀時正在關閉流的可能性。

+0

不,你描述了當你使用BeginInvoke時會發生什麼。 OP正在使用Invoke。 – 2010-10-13 15:13:20

+0

好的。我編輯了我的答案。 – ctacke 2010-10-13 15:30:12

1

我在一些正在處理的嵌入式板(ARM)上看到了同樣的問題。然後我創建了一個小測試。

下面的代碼(!不涉及任何線程)崩潰:

using (var w = new StreamWriter(File.Create("file.txt"), System.Text.Encoding.UTF8)) 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
      w.WriteLine("Test"); 
     } 
    } 

此代碼但不崩潰:

using (var w = File.CreateText("file.txt")) 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
      w.WriteLine("Test"); 
     } 
    } 

所以,我的猜測只能是潛在的本地代碼對待文本文件與使用File.Create()打開文件時不同。這兩個文件都是用UTF-8編寫的,所以編碼沒有區別。

BTW:對不起,我算是今年年底的答案,但我希望這會幫助別人

相關問題