我使用FileStream
和FileMode.Open
打开FileAccess.Read
。不久之后,我调用一个函数来处理文件的内容。我使用Invoke
进行调用,因为调用来自Thread
,函数必须将结果放在Form
上。该函数接受任何类型的流(我也称之为MemoryStream
s而没有问题)并使用XmlTextReader
来读取FileStream
中的XML,但在极少数情况下甚至出于未知原因第一个Read()
抛出ObjectDisposedException
,如果流已经关闭,则流的CanRead
属性返回false。
在Thread
中,FileStream
是一个本地using
变量,所以我认为其他线程不应该关闭它,我不会关闭它直到Invoke
返回了。没有Exceptions
被抛出,因此文件肯定存在(因为没有FileNotFoundException
)并且应该被正确访问(因为没有UnauthorizedAccessException
和IOException
)。< / p>
我的FileStream
有时候在打开之后仍然看起来像是关闭了吗?
(我可能在使用Compact Framework 3.5的Windows CE 5设备上运行我的代码并且我无法在使用XP的台式PC上重现相同的行为。)
修改 我知道,这个Invoke很丑陋,但仅凭这一点不能成为失败的理由,是吗? (并且,在大多数情况下,它根本不会失败。)
//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 :(得分:1)
当然,这是预期的行为。您调用Invoke,它将调用封送到另一个线程。然后调用线程继续运行并且使用块退出,在流上调用Dispose。在使用UI线程中的流完成之前(也许在开始之前),就会发生此Dispose。这些操作的确切时间取决于处理器负载和其他一些因素,但它肯定不安全。
要么将流放入使用块中,要么更好,让线程执行读取并通过Invoke将结果传递给UI。
修改强>
正如Hans在评论中指出的那样,上面的解释应该是一个BeginInvoke调用,它在下面调用PostMessage。另一方面,Invoke使用SendMessage。两者都可能使用一些WM_COPYDATA恶作剧(我没有看到)来编组数据。
Invoke调用应该执行您发布的整个处理程序,尽管您看到的行为表示不同。从您发布的代码中,我们无法确定关闭流的内容。
我仍然会重构你在这里所做的事情,因为现在你正在通过阅读器操作捆绑UI和工作线程。我将在工作线程中执行读取工作,然后将结果传递给UI。这样可以降低读者工作导致UI不稳定的几率,并且可以消除在您阅读流时关闭流的可能性。
答案 1 :(得分:1)
我能想到的一个原因是:工作线程被中止了。这将运行使用语句生成的finally块并关闭该文件。它如何被中止是一个次要问题。线程的IsBackground属性是否设置为true?该程序是否在其他地方发生未经处理的异常并且正在关闭?当然猜对了。
答案 2 :(得分: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编写,因此编码没有区别。
顺便说一句:对不起,我答案迟了一年,但我希望它会帮助某人