d.allen101 Ответов: 2

Нарезание резьбы.Таймер с WinForm


Я опрашиваю базу данных каждые 1/2 секунды с помощью потоковой передачи.Таймер и отображение результатов в форму элемент управления ListView. Результаты запроса возвращают около 150 строк, которые я изначально "добавляю" в listview. Как только listview заполнен, я больше не "добавляю" элементы, я перебираю каждую строку listview и обращаюсь к свойству TEXT, чтобы изменить содержимое каждой строки. Я делаю это, чтобы мне не пришлось очищать listview при каждом запросе, вызывая покраску listview и потерю его текущей позиции прокрутки...

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

Может ли кто-нибудь прояснить, что здесь происходит и что мне нужно сделать, чтобы сделать форму более отзывчивой и повысить эффективность обновления listview с новым результатом, но без перекраски listview и потери его текущей позиции прокрутки.

Заранее спасибо,
-Ди

BillWoodruff

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

Почему?

2 Ответов

Рейтинг:
0

Sergey Alexandrovich Kryukov

Что плохого в моем решении Опрос базы данных с таймером[^]?

Если вы запускаете опрос в отдельном потоке, обновление пользовательского интерфейса будет происходить через вызов потока пользовательского интерфейса. Даже если вы "обновите элемент управления вне основного потока" (я читаю его как "поток пользовательского интерфейса"), фактическое обновление произойдет в потоке пользовательского интерфейса из-за вызова. Вы просто не можете вызвать что-либо, связанное с пользовательским интерфейсом, из потока, не являющегося пользовательским интерфейсом. Вместо этого вам нужно использовать метод Invoke или BeginInvoke от System.Windows.Threading.Dispatcher (для обеих форм или WPF) или System.Windows.Forms.Control (Только бланки).

Вы найдете подробное объяснение того, как это работает, и примеры кода в моих прошлых ответах:
Контроль.Invoke() против Control.BeginInvoke()[^],
Проблема со сканером Treeview и MD5[^].

См. также дополнительные ссылки на потоковую обработку:
Как получить событие keydown для того чтобы работать в другом потоке, в vb.net[^],
Контроль событий, не срабатывающих после включения отключения + многопоточности[^].

—СА


d.allen101

Я борюсь! что я делаю не так? мой элемент управления listview не обновляется, и моя форма замораживается. вот как выглядит мой код:

MyDataObject myDatObj = новый MyDataObject;
Thread thrd = new Thread(new ParameterizedThreadStart(ListviewMethod));
thrd.Start(myDatObj);
EventWaitHandle ewh = new AutoResetEvent(false);
делегат void ListviewDel(объект dataObj);
ПМР таймер = новый таймер();
tmr.интервал = 500;
ПМР.ТИК += новый EventHandler(OnListview_Tick);
ПМР.Начать();

OnListviewTick недействительным(объект отправителя, EventArgs в электронной)
{
ЭВН.Набор();
}

void ListviewMethod(object obj)
{
в то время как(правда)
{
фу.Метод waitone();

если(мыши listview1.Свойство invokerequired)
{
listview1.Invoke((ListveiwDel)ListviewMethod, myDatObj);
продолжить;
}

double a = myDatObj.Number1;
Дабл Би = myDataObj.Число2;
двойной c = myDataObj.Number3;

мыши listview1.Добавить(а);
мыши listview1.Добавить(б);
listview2.Добавить(с);
}
}

Sergey Alexandrovich Kryukov

Вам не нужен ParameterizedThreadStart - вы не используете obj. ParameterizedThreadStart-это плохо. Вместо этого я сказал вам использовать обертку для нитей. Метод ListView-это нестатический метод (экземпляр), он уже прошел "это". Попробуйте использовать событие ручного сброса. (Авто тоже может работать, но я сделал это вручную.) Я не знаю, что еще...

А, понятно!!! Проблема найдена!!!
В ListviewMethod вы вызываете тот же самый метод. Как ты мог это сделать??!!! Этот метод снова ждет. Нет, не делай этого. Создайте два отдельных метода: отдельный для обновления пользовательского интерфейса, а ListviewMethod должен только ждать, а затем вызывать метод обновления пользовательского интерфейса.

Я не могу этого вынести: такой распространенный недостаток. Почему вы пытаетесь "сэкономить" (что-то: -) на методах? Не иметь смысла.
--СА

d.allen101

СА, я запутался! я уже несколько раз готовил ваше решение и читал ваши статьи о потоковой передаче: я пытаюсь реализовать то, что вы предложили, но, похоже, не могу сделать это правильно. не могли бы вы указать на пример, который реализует это, пожалуйста?

d.allen101

правильно ли это? :

делегат void LstVwDel();

MyDataObj myDatObj = новый MyDataObj();
LstVwDel lstVwDel = новый LstVwDel(updateLv);
Thread thrd = Новый Поток(updateThread);
thrd.Начать();
EventWaitHandle ewh = AutoResetEvent(false);
ПМР таймер = новый таймер();
tmr.интервал = 500;
ПМР.ТИК += новый EventHandler(threadThrottle_Tick);
ПМР.Начать();

threadThrottle_Tick недействительным(объект отправителя, EventArgs в электронной)
{
ЭВН.Набор();
}

пустота updateThread()
{
в то время как(правда)
{
фу.Метод waitone();
Вызов(lstVwDel);
}
}

пустота updateLv()
{
if(listview1.Предметы.Граф < 1)
{
мыши listview1.BeginUpdate();

для(i = 0; i < myDatObj.Numbers.Граф; i++)
{
double a = myDatObj.Number1[i];
double b = myDatObj.Number2[i];
double c = myDatObj.Number3[i]

мыши listview1.Предметы.Добавить(а);
мыши listview1.Предметы.подпункты.Добавить(b);
мыши listview1.Предметы.подпункты.Добавить(c);
}
мыши listview1.EndUpdate();
}
еще
{
мыши listview1.BeginUpdate();

for(int i = 0; i < myDatObj.Numbers.Граф; i++)
{
double a = myDatObj.Number1[i];
double b = myDatObj.Number2[i];
double c = myDatObj.Number3[i];

мыши listview1.Элементы[я].Текст = a;
мыши listview1.Элементы[я].Подпункты[1].Текст = b;
мыши listview1.Элементы[я].Подпункты[2].Текст = c;
}
мыши listview1.EndUpdate();
}
}

d.allen101

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

Рейтинг:
0

saberw

Попробуйте установить свойство double buffered в true.

Кроме того, вы могли бы использовать:




this.SuspendLayout();
this.listview.SuspendLayout();


//update control  
//put listview manipulation code hrer to not cause refresh form



this.listview.ResumeLayout(false);
this.ResumeLayout(false);


Dave Kreskowiak

Вы понимаете, что вопрос, на который вы написали это, старше семи лет?

saberw

Знаете ли вы, что каждый вопрос имеет более правильный ответ без учета времени?
Дорогие ученики могут использовать его.

Dave Kreskowiak

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