Member 3652617 Ответов: 2

Запутался в статике


У меня есть программа на C#. Я наблюдаю за каталогом для изменений в xml-файле, и когда файл изменяется, я хочу подготовить xml и обновить rich textbox.
Все это работает, когда я указываю файл. Он читает его и заполняет RTB нормально. Но когда я добавляю код, чтобы попытаться сделать это автоматически при изменении файлов, я получаю ошибку

Ошибка 1 Ссылка на объект требуется для нестатического поля, метода или свойства 'xml_reader.Form1. readXML (строка)'

Я читал несколько примеров на эту тему,но все еще не понимаю.

это срабатывает, когда должно
private static void OnChanged(object source, FileSystemEventArgs e)
 {
     // Specify what is done when a file is changed, created, or deleted.
     string path = e.FullPath;
     Console.WriteLine("File: " + path + " " + e.ChangeType);
    readXML(path);
 }


Я хочу позвонить
private void readXML(string Filename)
{
    int linenumbers = 0;
    string stringvalue;
    string stringname;
    String title = "POS           PILOT                 LAPS    ELAPSED      SEED         FAST LAP \n";
    richTextBox1.Text = title;
    XmlTextReader reader = new XmlTextReader(Filename);
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element: // The node is an element.
                if (reader.Name == "Driver")
                {

                    while (reader.MoveToNextAttribute()) // Read the attributes.
                    {
                        stringvalue = reader.Value;
                        stringname = reader.Name;
                        if (stringname == "position")
                        {
                            richTextBox1.Text += (" " + stringvalue + "\t");
                        }
                        if (stringname == "name")
                        {
                            string longname = stringvalue;
                            longname = longname.PadRight(30);
                            int namelength = longname.Length;
                            Console.WriteLine(longname + namelength);
                            richTextBox1.Text += (longname);
                        }
                        if (stringname == "laps")
                        {
                            if (stringvalue == " ")
                                stringvalue = "0";
                            richTextBox1.Text += ("  " + stringvalue + "\t\t");
                        }
                        if (stringname == "seed")
                        {
                            if (stringvalue == " ")
                                stringvalue = "0.000";
                            richTextBox1.Text += (stringvalue + "\t\t");
                        }
                        if (stringname == "elapsedTime")
                        {
                            if (stringvalue == " ")
                                stringvalue = "0.000";
                            richTextBox1.Text += (" " + stringvalue + "\t\t");
                        }
                        if (stringname == "fastLap")
                        {
                            if (stringvalue == " ")
                                stringvalue = "0.000";
                            stringvalue = stringvalue.PadRight(8);
                            richTextBox1.Text += (" " + stringvalue + Environment.NewLine);
                            linenumbers++;
                        }
                    }
                }
                break;
            case XmlNodeType.Text: //Display the text in each element.
                break;
            case XmlNodeType.EndElement: //Display the end of the element.
                break;
        }
    }
    reader.Close();
    colorTextbox(linenumbers);
}



Если я изменю функцию так ,чтобы она была " static void readXML(string Filename)"
затем я получаю ошибки на richtextbox1.

Какой самый простой способ это исправить?
Заранее спасибо.

Что я уже пробовал:

делая вызываемую процедуру статичной.

Matt T Heffron

Попробуйте удалить статику из метода OnChanged.

2 Ответов

Рейтинг:
15

Sergey Alexandrovich Kryukov

Метод должен быть статическим, если вам просто не нужно "это", которое является ссылкой на экземпляр некоторого класса. Это" это " является неявным методом, который передается всем метод экземпляра(Таким образом, "метод экземпляра" является антонимом "статического метода".) Вы можете вызвать метод экземпляра только для некоторого экземпляра (instanceName.MethodName(/* … */)) и вы можете вызвать только статический метод по типу (TypeName.MethodName(/* … */)), так что этот экземпляр становится ссылкой на экземпляр, переданный методу экземпляра.

Вы можете получить доступ ко всем членам типа через "это", и, следовательно, из статического метода вы можете получить доступ только к статическому члену. Использование статических методов на практике является обязательным, когда у вас есть методы, не связанные с другими членами, например некоторые математические вычисления, работающие только с параметрами.

Для получения более подробной информации, пожалуйста, ознакомьтесь с моими прошлыми ответами:
Приведение типов в C#,
C# windows base это ключевое слово связано и его использование в приложении,
Что делает статические методы доступными?.

Использование статического метода в качестве некоторого обработчика событий возможно, но крайне маловероятно, что он окажется полезным. Это объясняет комментарий к вопросу Мэтта ти Хеффрона.

—СА


Matt T Heffron

+5 к незаслуженному противодействию 1 голосу.

Sergey Alexandrovich Kryukov

Спасибо, Мэтт.
—СА

Afzaal Ahmad Zeeshan

5ed; просто говорю, что в C# у всех шапки как TypeName. ;-) Но это не имеет значения, хороший ответ.

Sergey Alexandrovich Kryukov

Спасибо, Afzaal.
Вы имеете в виду соглашения об именах Microsoft? Вы правы, это то, что я хотел написать; я исправлю это — спасибо за исправление.
—СА

Рейтинг:
1

Matt T Heffron

В дополнение к моему комментарию выше о том, чтобы сделать метод OnChanged не статичным, есть и другие вещи, очень неправильные в вашем коде. Не в последнюю очередь это злоупотребление конкатенацией строк! Вы должны использовать Класс StringBuilder (System. Text)[^]:

private void readXML(string Filename)
{
  int linenumbers = 0;
  string stringvalue;
  const string title = "POS           PILOT                 LAPS    ELAPSED      SEED         FAST LAP \n";
  StringBuilder builder = new StringBuilder(title, 1024); // 1k is a fair starting "guess" ;-)
  using (XmlTextReader reader = new XmlTextReader(Filename))
  {
    // The using statement ensures that reader is Closed when done.
    while (reader.Read())
    {
      switch (reader.NodeType)
      {
      case XmlNodeType.Element: // The node is an element.
        if (reader.Name == "Driver")
        {
          while (reader.MoveToNextAttribute()) // Read the attributes.
          {
            stringvalue = reader.Value;
            switch (reader.Name)
            {
            case "position":
              builder.Append(" ").Append(stringvalue).Append("\t");
              break;
            case "name":
              string longname = stringvalue.PadRight(30);
              Console.WriteLine("{0} {1}", longname, longname.Length);
              builder.Append(longname);
              break;
            case "laps":
              if (string.IsNullOrWhiteSpace(stringvalue))
                stringvalue = "0";
              builder.Append("  ").Append(stringvalue).Append("\t\t");
              break;
            case "seed":
              if (string.IsNullOrWhiteSpace(stringvalue))
                stringvalue = "0.000";
              builder.Append(stringvalue).Append("\t\t");
              break;
            case "elapsedTime":
              if (string.IsNullOrWhiteSpace(stringvalue))
                stringvalue = "0.000";
              builder.Append(" ").Append(stringvalue).Append("\t\t");
              break;
            case "fastLap":
              if (string.IsNullOrWhiteSpace(stringvalue))
                stringvalue = "0.000";
              stringvalue = stringvalue.PadRight(8);
              builder.Append(" ").AppendLine(stringvalue);
              linenumbers++;
              break;
            default:
              break;
            }
          }
        }
        break;
      case XmlNodeType.Text: //Display the text in each element.
        break;
      case XmlNodeType.EndElement: //Display the end of the element.
        break;
      }
    }
  }
  // Edit: Matt Heffron: 6/17/2016
  // Dealing with the Cross-thread access error:
  // Was:
  richTextBox1.Text = builder.ToString();
  // Change to:
  Action updateText = () => richTextBox1.Text = builder.ToString();
  if (richTextBox1.InvokeRequired)
    richTextBox1.Invoke(updateText);
  else
    updateText();
  // End of Edit
  colorTextbox(linenumbers);
}

Кроме того, табличные данные, подобные этому, были бы лучше представлены с помощью DataGrid контроль вместо а RichTextBox.


Sergey Alexandrovich Kryukov

На этот раз я проголосовал за 4. У вас есть несколько очень хороших моментов, но статические методы vs instance не объясняются.
Да, я знаю, очень трудно объяснить основы вкратце, особенно людям, которые пытаются сделать что-то продвинутое, не понимая основ. Это главная проблема большинства наших исследователей, не так ли?

Я попытался объяснить это в решении 2,приписывая ваш комментарий к этому вопросу.

—СА

Member 3652617

Спасибо, Мэтт, я обязательно посмотрю на сетку данных.Я внес изменения в строку, которую вы опубликовали. Когда я удаляю статику из метода Onchange, я получаю ошибку в строке
richtextbox1 отображение.Текст = построитель.Метод toString();
Я предполагаю, что получил бы ту же ошибку, если бы это была сетка данных. Ошибка заключается в следующем
Необработанное исключение типа ' System.InvalidOperationException ' произошло в системе.Окна.Forms.dll

Дополнительная информация: операция Кросс-потока недопустима: управление 'richTextBox1' осуществляется из потока, отличного от потока, в котором оно было создано.

Наверное, именно это Сергей и пытался объяснить ниже, но это прошло мимо моей головы. Я явно не программист. Спасибо за объяснение, и я прочитаю его еще несколько раз, но не могли бы вы помочь мне и с этой ошибкой, пожалуйста. спасибо снова.

Matt T Heffron

Ошибка Кросс-потока возникает из-за того, что вы выполняете это в другом потоке, отличном от потока пользовательского интерфейса. Свойства / методы элементов управления пользовательского интерфейса должны быть доступны из потока пользовательского интерфейса. Есть свойство и метод на элементах управления, чтобы справиться с этим.
См. мое обновление решения.
Если метод colorTextbox (или любой другой метод) обращается к любым элементам управления пользовательского интерфейса из потока Кроме как в потоке пользовательского интерфейса тогда эта же ошибка возникнет и там. Вам нужно будет найти и исправить все это!

Member 3652617

Спасибо, я не мог заставить его работать с линией
Действие updateText = () => {richTextBox1. Text = builder.Метод toString();}
поэтому я достал бракеты и сделал это
Действие updateText = () = & gt; richTextBox1.Text = builder.Метод toString();
не уверен, что это сломало его или нет, но теперь ошибка
на линии в то время как(читатель.Читать())
и его необработанное исключение типа "System. IO.IOException" произошло в System.Xml.dll

Дополнительная информация: процесс не может получить доступ к файлу 'C:\Users\ldavis\Dropbox\RC\DRC\xml\driverData.xml-потому что его использует другой процесс.

Matt T Heffron

На самом деле все, что вам нужно было, это a ; после} (ой!)
Исключение IOException означает, что какой-то другой процесс имеет этот файл открытым, вероятно, для записи. Поскольку вы вызываете это из-за измененного события FileWatcher, вам нужно немного подождать после "последнего" измененного события, чтобы определить, является ли файл измененным и "читаемым". Как долго, зависит от того, как записывается файл.

Member 3652617

В этом есть смысл. Я вставил злую нить ... сон, и это все исправило. Теперь я "думаю", что мне просто нужна еще 1 часть синтаксической помощи.
в setupdatagrid я использовал
если (это.Свойство invokerequired)
{
этот.Invoke(new Action (() = & gt; setupdatagrid()));
}
и это работает, но я не могу понять синтаксис для
colorTextbox(int lines) делает то же самое.
Смотрите ниже и спасибо за всю помощь




< pre lang= "c#" & gt;использование системы;
использование системы.Коллекции.Общий;
использование системы.ComponentModel;
используя системы.Сведения;
использование системы.Рисование;
использование System. Linq;
используя системы.Текст;
использование системы.Нарезание резьбы.Задачи;
использование системы.Окна.Формы;
использование System.Xml;
использование системы.ИО;
использование системы.Безопасность.Разрешения;


пространство имен xml_reader
{

общественности частичного класс form1 : форма
{
строковое имя файла;
открытый form1()
{
метод InitializeComponent();
setupdatagrid();

}

частный недействительными методе form1_load(объект отправителя, EventArgs в электронной)
{
richtextbox1 отображение.Многострочный = истина;
// richtextbox1 отображение.AcceptsTab = истина;
richtextbox1 отображение.SelectionColor = Цвет.Красный;


}

частная btn_read_Click недействительным(объект отправителя, EventArgs в электронной)
{
Диалоговое окно openfiledialog openFileDialog1 = новое диалоговое окно openfiledialog();
// Установите параметры фильтра и индекс фильтра.
openFileDialog1.Filter = " XML-файлы (*. xml)|*. xml";
openFileDialog1.FilterIndex = 1;
if (openFileDialog1.ShowDialog () = = DialogResult.ОК)
{
filename = openFileDialog1.имя файла;
readXML(openFileDialog1.имя файла);

FileSystemWatcher watcher = новый FileSystemWatcher();
строку каталог название = Путь.GetDirectoryName(openFileDialog1.имя файла);
наблюдатель.Путь = каталог название;
наблюдатель.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Каталог название;
// Смотрите только xml-файлы.
наблюдатель.Filter="*. xml";

// Добавить обработчики событий.
наблюдатель.Изменено += новый FileSystemEventHandler(OnChanged);
наблюдатель.Created += new FileSystemEventHandler(OnChanged);

// Начинайте смотреть.
// таймера1.Включен = истина;
// или
наблюдатель.EnableRaisingEvents = true;

}
}

частный недействительными событий onchanged(источник, объект, FileSystemEventArgs е)
{
// Укажите, что делается при изменении, создании или удалении файла.
string path = e. FullPath;
Приставка.WriteLine ("File:" + path + "" + e. ChangeType);
Система.Нарезание резьбы.Нить.Спать(1000);
readXML(путь);
}

private void readXML(строковое имя файла)
{
int linenumbers = 0;
string stringvalue;
строка Pos = " POS";
string Pilot = " пилот";
строку кругов = "кругов";
строки прошедшее = "прошедшее";
исходная строка = "семя";
строка быстрого = "быстрого круга";
строка [] строка;
setupdatagrid();

константная строка заголовок = "поз пилот кругов прошедшее семян быстром круге \Н";
StringBuilder builder = new StringBuilder(title, 1024); / / 1k-это справедливое начальное " предположение" ;-)
используя (типа xmltextreader читатель = новый класс xmltextreader(именем))
{
// Оператор using гарантирует, что reader будет закрыт после завершения работы.
в то время как (читатель. читать())
{
переключатель (читатель.Типа)
{
случай XmlNodeType.Элемент: / / узел является элементом.
если (читатель.Имя = = " Водитель")
{
в то время как (читатель.MoveToNextAttribute()) // читаем атрибуты.
{
stringvalue = reader.Ценность;
переключатель (reader.Name)

Member 3652617

Ой, наверное,я не могу выложить столько кода.
таким образом, рабочая функция

частный недействительными setupdatagrid()
{

если (это.Свойство invokerequired)
{
этот.Invoke(new Action (() = & gt; setupdatagrid()));
}
ещё
{
dataGridView1.Строк.Четкий();
dataGridView1. ColumnCount = 6;
.......

а вот чего я никак не могу понять, так это
private void colorTextbox(int lines)
{
если (это.Свойство invokerequired)
{
этот.Invoke(new Action (() => colorTextbox ()));/ / каков правильный синтаксис?
}
ещё
{

int lineNumberToSelect = 0;
...........

Matt T Heffron

Нам обоим было бы лучше, если бы вы перепостили этот вопрос как новый вопрос с хорошим названием и описанием, а также код, отформатированный с тегами " pre...".
Это также облегчает поиск для будущих людей, ищущих решение подобной проблемы.

Hrishikesh Ranjit Shivacharan

Когда вы обращаетесь к нестатическому методу в статическом методе, это неправильно в языке программирования.