Удалить текст из RichTextBox

Моя проблема: у меня есть событие DataReceived для SerialPort, которое прослушивает последовательный порт и добавляет все в RichTextBox. Теперь я хотел бы сохранить содержимое RichTextBox в текстовый файл. Я мог бы сделать это:

string text = RichTextBox.Text;
// save file
RichTextBox.Clear();

Но я боюсь (и, пожалуйста, поправьте меня, если я ошибаюсь), что только между двумя моими действиями (сохранение содержимого в переменной, очистка RichTextBox) в SerialPort может прийти другой ввод. Поскольку я не сохранил их в свою переменную и сразу после этого очищаю RichTextBox, эти новые данные можно было удалить, даже не зная, что они когда-либо существовали.

Может ли такое быть на самом деле и как этого избежать?

Спасибо


person sventevit    schedule 15.09.2009    source источник


Ответы (3)


Вы должны как-то синхронизировать свои входы с последовательного порта. Я предполагаю, что вы используете Invoke в событии DataReceived. Таким образом, любые изменения содержимого RichTextBox выполняются основным потоком, и вы должны быть в безопасности.

Но поскольку поток из последовательного порта вряд ли будет RTF (у вас были бы другие проблемы, если бы это было так), вы могли бы также использовать TextBox (MultLine=true).

person Henk Holterman    schedule 15.09.2009
comment
Я пишу в RichTextBox с помощью Invoke (из потока DataReceived), поэтому запись и чтение выполняются в одном потоке (графический интерфейс). Что значит, что мой сценарий не мог произойти? - person sventevit; 15.09.2009
comment
На первый взгляд, я не думал, что использование Invoke защитит вас, но теперь, когда я все обдумал, это вас защитит. Хороший ответ! +1 - person David; 15.09.2009
comment
Я использую RichTextBox, потому что я проверяю каждый ввод с последовательного порта в SQL и возвращаю его статус. Если статус «ОК», то цвет текста для этого ввода зеленый, если не в порядке, цвет текста красный. Таким образом, оператор может легко увидеть, в порядке ли ввод или нет... - person sventevit; 15.09.2009

Это может произойти, если вы используете несколько потоков. В однопоточном приложении эта проблема не возникает.

Чтобы предотвратить это, вы можете использовать мьютекс. Вот как это работает: фрагменты кода, работающие с содержимым RichTextBox, не должны выполняться одновременно. Эти фрагменты кода называются критическими секциями. Когда вы входите в критическую секцию, вы блокируете мьютекс и освобождаете его при выходе из критической секции. Если мьютекс заблокирован, когда вы пытаетесь войти в критическую секцию, подождите, пока этот мьютекс будет освобожден, а затем выполните свою работу.

Таким образом, если какой-либо ввод поступает через последовательный порт во время записи в файл, поток, получающий данные, будет ждать завершения ввода-вывода файла, а затем добавит его в RichTextBox.

Этого можно добиться с помощью оператора lock. в С#.

Дополнительная литература: Mutex, Критический раздел

person erelender    schedule 15.09.2009
comment
Самостоятельная синхронизация не сработает, элементы управления проверяют ThreadId и выбрасывают. Вы должны использовать Invoke(). - person Henk Holterman; 15.09.2009

Абсолютно так могло бы случиться (и, вероятно, произошло бы).

Если нет других соображений, я считаю, что вам будет лучше использовать данные из потока SerialPort для прямой записи текстового файла, а не для записи в файл с помощью RichTextBox.Text. Обработчик события DataReceived должен выглядеть примерно так...

private void SerialPort1.DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   string DataText = // code to read the serialport data and convert 
   //it into a string, which you already have so I 
   //won't repeat it here.

   WriteToTextBox(DataText);
   WriteToFile(DataText);
}
person David    schedule 15.09.2009
comment
В событии DataReceived я сначала пишу текст в базу данных SQL, затем показываю его в RichTextBox, чтобы оператор мог видеть на экране то, что было отсканировано. Сохранение в текстовый файл — это еще один вариант для оператора (если что-то не так, он может просто сохранить текст в файл и отправить его администратору). - person sventevit; 15.09.2009