Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 监视文本文件中更改的内容可防止写入该文件_C#_Console Application_Updates_Inotifypropertychanged - Fatal编程技术网

C# 监视文本文件中更改的内容可防止写入该文件

C# 监视文本文件中更改的内容可防止写入该文件,c#,console-application,updates,inotifypropertychanged,C#,Console Application,Updates,Inotifypropertychanged,我有一个文本文件,文件中的值正在读入应用程序(控制台应用程序)。我想在文本文件中的值更改时更新应用程序中的值。我已经提到了这一点,并做了一些修改。结果是,当我更改文本文件中的值并尝试保存它时,应用程序中的值不会更新,因为无法保存该文件 如果更改文本文件中的值,如何更新应用程序中的值 class Program { static void Main(string[] args) { TestClass sample = new Tes

我有一个文本文件,文件中的值正在读入应用程序(控制台应用程序)。我想在文本文件中的值更改时更新应用程序中的值。我已经提到了这一点,并做了一些修改。结果是,当我更改文本文件中的值并尝试保存它时,应用程序中的值不会更新,因为无法保存该文件

如果更改文本文件中的值,如何更新应用程序中的值

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"));
            }
        }
    }

代码中至少存在三个严重问题:

  • 在读取文件时,您会不断进行轮询,这将为任何其他进程写入文件留下很少的时间(基本上没有时间)
  • 无论属性值是否实际更改,只要调用属性设置程序,都会引发
    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选项(至少检查修改时间戳)就可以了。

    代码中至少存在三个严重问题:

  • 在读取文件时,您会不断进行轮询,这将为任何其他进程写入文件留下很少的时间(基本上没有时间)
  • 无论属性值是否实际更改,只要调用属性设置程序,都会引发
    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选项(至少检查修改时间戳)就可以了。

    不确定循环是否导致了此问题。你能利用Hi@qxg吗?谢谢你的评论。在实际环境中,文本文件中的值将是配置应用程序(连接到配置服务器)中的值,我可以从配置应用程序中检索该值,但一旦该值发生更改,就无法更新应用程序中的值。对于上面的问题,我只给出了一个与实际问题类似的简单示例。您的代码对我很有用。检查其他问题。在我运行我的应用程序后,该值不断循环,当我更改文本文件中的值时,它不允许我保存,因为该文件被其他程序使用。这只是文件系统问题?所以问题不在于如何实现
    INotifyPropertyChanged
    (当然,通过比较
    TestValue
    属性中的旧值来检查值是否真的发生了更改)。您在如何从其他应用程序/服务器读取值方面遇到问题。如果可能,请更新问题。不确定循环是否导致此问题。你能利用Hi@qxg吗?谢谢你的评论。在实际环境中,文本文件中的值将是配置应用程序(连接到配置服务器)中的值,