Имеется "textBox" (многострочный), заполняется сообщениями из "serialPort" и при добавлении новых строк прокручивается вверх (как уже все знают). Знаю что исправляется это методами
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();
Но у меня многопоточность и прямое обращение к форме созданной в другом потоке "не безопасно". Для вызова метода "textBox.Text" есть специальный способ с применением "invoke" и delegate. Надеюсь что для вызова других его методов тажке есть способ, однако я так и не нашел его.
Я применил хитрость (глупость) и вызвал "прокрутку списка" по событию textBox1_TextChanged()
, но тогда текст прыгает вверх и вниз как безбашенный, сперва прокручиваясь вверх по принятию новой строки, а потом вниз по событию "text changed".
UPDATE: Оказалось что список скачет как бешеный во всех случаях при использовании способа textBox.Text += "something";
и постоянно печатающегося текста.
Решение этой проблемы в использовании другого способа печатать в textBox: textBox.AppendText("something");
, а если вам нужна новая строка то: textBox.AppendText(Environment.NewLine);
этот метод автоматически прокручивает "textBox" в конец текста
Этот метод быстрее и намного стабильнее (как я заметил).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace factyWinDBIntrf01
{
public partial class Form1 : Form
{
private Thread readingThread;
public Form1()
{
InitializeComponent();
getAvailPorstList();
}
void getAvailPorstList()
{
String[] portsList = SerialPort.GetPortNames();
selectCOMPort.Items.AddRange(portsList);
}
private void groupBox2_Enter(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
try
{
textBox1.Text += serialPort1.ReadLine();
textBox1.Text += "\n";
}
catch (TimeoutException)
{
textBox1.Text = "Receive Timeout";
}
}
private void button4_Click(object sender, EventArgs e)
{
try
{
if (selectCOMPort.Text == "")
{
textBox1.Text = "COM Port is not selected";
}
else if (comboBox1.Text == "")
{
textBox1.Text = "Baud rate is not set";
}
else
{
serialPort1.PortName = selectCOMPort.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox1.Text);
serialPort1.Open();
progressBar1.Value = 100;
textBox1.Enabled = true;
textBox2.Enabled = true;
button2.Enabled = true;
button3.Enabled = true;
selectCOMPort.Enabled = false;
button4.Enabled = false;
button5.Enabled = true;
readingThread = new Thread(readSerial);
readingThread.Start();
}
}
catch (UnauthorizedAccessException)
{ textBox1.Text = "Unauthorized Access"; }
}
private void button5_Click(object sender, EventArgs e)
{
readingThread.Abort();
serialPort1.Close();
progressBar1.Value = 0;
textBox1.Enabled = false;
textBox2.Enabled = false;
button2.Enabled = false;
selectCOMPort.Enabled = true;
button4.Enabled = true;
button5.Enabled = false;
}
private void button3_Click(object sender, EventArgs e)
{
serialPort1.WriteLine(textBox2.Text);
}
void readSerial()
{
while (serialPort1.IsOpen)
{
try
{
if (serialPort1.IsOpen)
{
textBox1_TextSafe(serialPort1.ReadLine());
textBox1_TextSafe("\n");
//DOESN'T WORK FOR MULTITHREAD CODE
//textBox1.Text += serialPort1.ReadLine();
//textBox1.Text += "\n";
}
}
catch (TimeoutException)
{
textBox1.Text = "Receive Timeout";
}
//not needed //Tread.Sleep(0);
}
}
delegate void StringArgReturningVoidDelegate(string text);
private void textBox1_TextSafe(string text)
{
if(textBox1.InvokeRequired)
{
StringArgReturningVoidDelegate d = new StringArgReturningVoidDelegate(textBox1_TextSafe);
Invoke(d, new object[] { text });
//-1@ NEED SOMETHING LIKE THIS I GUESS
//textBox1.SelectionStart = textBox1.Text.Length;
// textBox1.ScrollToCaret();
//textBox1.Refresh();
}
else
{
textBox1.Text += text;
//-1@ AND THIS
//textBox1.SelectionStart = textBox1.Text.Length;
//textBox1.ScrollToCaret();
//textBox1.Refresh();
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//-2@ STUPID IDEA
//textBox1.SelectionStart = textBox1.Text.Length;
//textBox1.ScrollToCaret();
//textBox1.Refresh();
}
}
}
Попробуйте так
textBox.Invoke(new Action(() =>{
// делайте все, что вам нужно сделать в UI
}));
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Добрый вечер господа, нужна помощь человека который хорошо разбирается в Java с целью анализа имеющегося исходного кода программы, так как...
Я решил установить Visual studio 2017 enterprise и возник вопрос: где поставить галочки для разработки на c#Знаю что можно позже установить оставшийся...
Столкнулся с проблемой байдинга даты и времениИдея такая: дата выбирается в CalendarDatePicker, а время указывается в TimePicker
На форме расположен ToolStrip, в котором есть несколько кнопокПри нажатии на кнопку отрабатывает событие ItemClicked, затем отрабатывает метод Click конкретной...