我有一个文本文件,文件中的值正被读入应用程序(控制台应用程序)。我想更改文本文件中的值时更新应用程序中的值。我已经提到了这个link并做了一些修改。结果是当我更改文本文件中的值并尝试保存它时,应用程序中的值不会更新,因为无法保存文件。
如果更改文本文件中的值,如何更新应用程序中的值?
class Program
{
static void Main(string[] args)
{
TestClass sample = new TestClass();
sample.PropertyChanged += new PropertyChangedEventHandler(sample_PropertyChanged);
while (true)
{
using (StreamReader sr = new StreamReader("Testing.txt"))
{
// Read the stream to a string, and write the string to the console.
string str = sr.ReadToEnd();
sample.TestValue = str;
}
}
}
static void sample_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
TestClass sample = (TestClass)sender;
/*
* Use expression behind if you have more the one property instead sample.TestValue
* typeof(TestClass).GetProperty(e.PropertyName).GetValue(sample, null)*/
Console.WriteLine("Value of property {0} was changed! New value is {1}", e.PropertyName, sample.TestValue);
}
}
public class TestClass : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
string testValue = string.Empty;
public string TestValue
{
get { return testValue; }
set
{
testValue = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TestValue"));
}
}
}
答案 0 :(得分:0)
您的代码中至少存在三个严重问题:
PropertyChanged
事件。PropertyChanged
事件。这不必要地延长了文件保持打开的时间段(实际上,它会使事件处理程序可以强制文件在任意长时间内保持打开状态)。上述最简单的修复方法如下所示:
while (true)
{
string str = File.ReadAllText("Testing.txt");
sample.TestValue = str;
Thread.Sleep(1000); // sleep for 1 second
}
和此:
public string TestValue
{
get { return testValue; }
set
{
if (testValue != value)
{
testValue = value;
// BUGBUG: Warning! This code is not thread-safe; it is possible for
// the current thread to check `PropertyChanged` just before some other
// thread changes its value to null, and then to try to invoke the handler
// just _after_ that other thread changes its value to null. This is fine
// if you are sure that the event and property are both only ever accessed
// in one single thread. But otherwise, you need to fix this bug, by
// following the normal C# idiom for raising events, i.e. store the field
// value in a local variable, and then if it's non-null, raise the event
// using the local variable's value instead of the event field itself.
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TestValue"));
}
}
}
请注意上面代码中关于您在处理活动时可能存在的错误的评论。
除此之外,您还可以对代码进行其他一些改进:
File.GetLastWriteTimeUtc()
检查文件的文件修改时间戳,如果时间戳比上次检查时更新,则只打开文件进行读取。这样可以避免不必要地打开文件,从而减少文件锁定冲突的可能性。FileSystemWatcher
为您完成工作,只在Changed
事件被引发时才读取文件。这样做的主要缺点是FileSystemWatcher
并不总是(事实上,通常不会)及时通知文件的更改。它最终将引发相应的事件,但它跟踪的目录信息本身并不总是由Windows及时更新,导致在收到更改通知时出现延迟(最多几十秒,根据我的经验)。 如果您可以接受,例如在收到通知之前会有一分钟的延迟,然后我会推荐FileSystemWatcher
。否则,只需每秒(或不太频繁)轮询,或者至少检查修改时间戳的#1选项,就可以了。