Рейтинг:
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, чем в вашем ответе, который является лишь небольшим подмножеством того, что было обсуждено.