![]() |
Модераторы: Partizan, gambit |
![]() ![]() ![]() |
|
bobr |
|
|||
Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 23.2.2007 Репутация: нет Всего: нет |
Друзья, пишу текстовый редактор, хочется, чтобы в программе было несколько потоков.
1-ый поток - основной. 2-ой поток отслеживает позицию курсора (номер линии, на которой курсор находится) и выводит эту текущую позицию в некоторый textBox. Пишу 2-ой поток таким образом: public class ThreadClass { public void Execute() { while (true) { textBox1.Text = richTextBox1.SelectionStart+" "; Thread.Sleep(100); } } } а мне выдаются ошибки вида: Error 7 Cannot access a nonstatic member of outer type 'TeEd.TeEdForm' via nested type 'TeEd.TeEdForm.ThreadClass' E:\Documents and Settings\1\Рабочий стол\textEd1\TeEd\TeEdForm.cs 69 24 TeEd Error 8 Cannot access a nonstatic member of outer type 'TeEd.TeEdForm' via nested type 'TeEd.TeEdForm.ThreadClass' E:\Documents and Settings\1\Рабочий стол\textEd1\TeEd\TeEdForm.cs 69 40 TeEd помогите разобраться, в чем дело. (если можно, напишите кусочек кода) Заранее спасибо. |
|||
|
||||
marcusmae |
|
|||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 22 Всего: 39 |
bobr,
до кусочка работающего кода, боюсь, сразу дело не дойдёт, поскольку ошибка состоит в том, что нестатические (то есть, экземплярные) поля textBox1 и richTextBox1, которые компилятор квалифицирует как относящиеся к outer (то есть, внешнему по отношению к ThreadClass) типу TeEd.TeEdForm, не могут быть употреблены в nested (то есть, вложенном) типе ThreadClass. Упрощая, та же самая ошибка содержится в следующем фрагменте :
Это сообщение отредактировал(а) marcusmae - 6.4.2008, 22:19 -------------------- ἀπὸ μηχανῆς θεός |
|||
|
||||
bobr |
|
|||
Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 23.2.2007 Репутация: нет Всего: нет |
Друзья, если есть возможность, объясните в общих чертах, как справиться с такой задачей.
есть поле richTextBox, в нем пишут текст, нужно, чтобы параллельно с этим основным потоком работал другой, определяющий в какой строчке находится курсор, и выводящий эту информацию в какой-нибудь textBox. marcusmae, спасибо за помощь, сделал эти классы "равнозначными", т.е. вынес один из другого, но прога не работает - выдается ошибка. Заранее всем спасибо. |
|||
|
||||
marcusmae |
|
||||||||||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 22 Всего: 39 |
Ну смотрите : вот класс ManagedRichTextBox. Он расширяет стандартный RichTextBox функциональностью, связанной с потоками, определяя следующие элементы :
Конструктор создаёт управляющий поток и связывает его с методом CursorThreadRunner. Поток не стартует немедленно, а "по требованию", если caller скомандовал :
Далее, в методе CursorThreadRunner происходит инициализация и старт таймера, который занимается отсчётом интервала, по прошествии которого периодически вызывает метод обновления координат курсора - UpdateCoordinates. Тот в свою очередь, как того требуют правила работы с формами, переключает поток и выполняет вычисление координат и обновление TextBox-ов. Само вычисление координат реализовано, через системный вызов посылки сообщения :
следующим заклинанием :
Чтобы сохранить интригу, данный код не вычисляет координаты в привычном понимании. Y - это индекс строки, но X - это абсолютный индекс символа - координата может быть из него получена различными способами. Теперь, когда RichTextBox более-менее грамотно расширен, как того требует задача, мы можем воспользоваться им в какой-нибудь форме :
Всё, что здесь делается - это, по сути, инициализация, старт потока, затем доопределение необходимых свойств TextBox-ов и добавление их на форму (опять, с переключением потока через this.Invoke). В качестве интервала обновления по умолчанию установлено 500 миллисекунд (0.5 сек), что довольно много : в тесте эта задержка слегка заметна при невысокой активности курсора. ![]() В двух вещах есть сомнения. Во-первых, я подозреваю, что сама идея с отдельным потоком неумна. Но это надо просто посмотреть как люди пишут текстовые редакторы - если Вы этим хотите серьёзно заняться, но наверняка сами посмотрите. Во-вторых, очень сомневаюсь, что от того, что я показываю решение есть какой-то толк, при том, какие Вы делаете ошибки - слишком трудно будет для начала. Осмелюсь посоветовать для начала набить руку на базовых вещах - различных конструкциях классов, событиях и других средствах платформы. Нет ничего плохого в том, чтобы учиться. Как только Вы наберёте опыт и будете чувствовать себя увереннее, всегда можно вернуться к этой задаче. Это сообщение отредактировал(а) marcusmae - 7.4.2008, 08:37 Присоединённый файл ( Кол-во скачиваний: 7 ) ![]() -------------------- ἀπὸ μηχανῆς θεός |
||||||||||
|
|||||||||||
bobr |
|
|||
Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 23.2.2007 Репутация: нет Всего: нет |
marcusmae, большое спасибо!!!
(читаю много литературы по Шарпу, но там в основном потоки рассмотрены на консольных примерах, здесь как раз проблем нет, у меня же проблема во взаимодействии классов...) основная моя проблема, в том, как из класса, образующего второй поток обратиться к объекту (textBox) основного класса. (понимаю, что вопрос дилетантский, но в C# делаю пока еще только первые шаги) Если вам не трудно, напишите маленький пример такого вида: дана простая форма с двумя textbox: tb1 и tb2. и есть второй поток, который читает информацию из tb1 и записывает ее в tb2. (на этом примере, думаю,у меня получится разобраться как класс потоков взаимодействует с объектами основного класса) |
|||
|
||||
marcusmae |
|
||||||||||||||||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 22 Всего: 39 |
Нормальный вопрос! Чтобы экземпляр объекта был доступен, он должен быть либо членом класса, либо переданным извне параметром в скобочках. Последнее, думаю, сразу понятно, а стать членом класса необходимый объект может либо в результате соответствующего наследования :
- все публичные (public) и защищённые (protected) элементы RichTextBox теперь есть и у ManagedRichTextBox, либо явно, по Вашему желанию :
Видно, что в предыдущем примере мне не пришлось никаким образом передавать textBox-ы в ManagedRichTextBox, потому что я создал их, во-первых, прямо в нём и, во-вторых, не на стороне основного потока, а на стороне вспомогательного :
Всё наоборот. Основная форма в начале своей жизни регистрируется на получение события о том, что вспомогательный поток сам создал textBox-ы :
- (см. в файле Form1.Designed.cs) После чего она стартует вспомогательный поток :
Если у вспомогательного потока всё получилось, то после создания textBox-ов он разошлёт уведомления всем слушателям события CursorsTextBoxesReady :
Среди слушателей обязательно окажется форма со своим обработчиком CursorTextBoxesReadyEventHandler, в котором подхватываются ссылки на textBox-ы и доопределяются всякие дизайнерские параметры. Всё это проделал всё тот же вспомогательный поток! Остаётся добавить textBox-ы на форму, чем, в силу устройства контролов, вспомогательный поток заниматься не может. Метод Invoke - это способ организации межпроцессорного взаимодействия между компонентами форм. При следующем вызове
процедура InitializeCursorManagment ставится на выполнение в очередь контрола this (то есть, самой формы), причём выполняется это не вспомогательным потоком, а тем, который создал форму, то есть основным. Одновременно с этим вспомогательный поток ведёт свои дела. Он устанавливает таймер, срабатывающий с заданным интервалом. Зарегестрированный на событие таймера Elapsed обработчик
вычисляет новые координаты курсора, опять же, через Invoke, поскольку обработчик сработал во вспомогательном потоке, но нужен Handle контрола ManagedRichTextBox, а ManagedRichTextBox создан основным потоком. Затем координаты сразу же попадают в textBox-ы. А с событием CursorsTextBoxesUpdated вышла оплошность. Вообще говоря, при нынешнем расположении, оно возникает раньше, чем обновляются координаты. Стоит поместить его после обновления координат textBox-ов. Но это не очень важно, поскольку оно не используется. Ну вот. Занимательный рассказ? ![]() -------------------- ἀπὸ μηχανῆς θεός |
||||||||||||||||
|
|||||||||||||||||
marcusmae |
|
||||||
![]() stravaganza ![]() ![]() Профиль Группа: Участник Сообщений: 874 Регистрация: 26.3.2006 Репутация: 22 Всего: 39 |
Окей, предыдущий вариант, возможно, на первый взгляд витееват, но у него есть и преимущества. Для разнообразия, поменяем схему : пусть оба textBox-а создаются основным потоком, а вспомогательный только играется с будильником.
Этот LinkedTextBox - это TextBox, расширенный необходимой функциональностью. Здесь явно присутствует передаваемый параметр (к Вашему вопросу), имеющий косвенное отношение к обоим textBox-ам : parentThreadControl.
В данном варианте форма регистрируется на событие, связанное с обновлением textBox-ов и сама занимается их текстом. Что для этого нужно сделать на стороне вспомогательного потока? Во-первых, словить срабатывание таймера. А во-вторых, при сигнализации необходимости обновления textBox-ов переключиться в основной поток, чтобы созданные в нём textBox-ы могли быть изменены. В отличие от предыдущего, этот вариант неудобен возможными проблемами при закрытии формы. Действительно, что будет, если форма вместе со своими textBox-ами уже начала освобождать ресурсы, а вспомогательный поток, как ни в чём не бывало, отправит туда предложение обновиться? = Будет вывалено исключение о попытке обратиться к объекту, который уже уничтожается (parentThreadControl, он же - экземпляр формы) ![]() ![]() Это сообщение отредактировал(а) marcusmae - 8.4.2008, 20:22 Присоединённый файл ( Кол-во скачиваний: 4 ) ![]() -------------------- ἀπὸ μηχανῆς θεός |
||||||
|
|||||||
Alexandr507 |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 70 Регистрация: 19.7.2009 Репутация: нет Всего: -1 |
В продолжении темы о потоках в windows form
Разрабатываю приложение в котором нужен второй поток, создал статический метод подскажите как туда передать всю форму попробовал что то типа этого, не получается
|
|||
|
||||
KelTron |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 745 Регистрация: 8.10.2006 Где: Красноярск Репутация: 9 Всего: 38 |
Только учти, что ничего хорошего не выйдет, если ты будешь пытаться из этого потока обращатсья к гую. http://msdn.microsoft.com/en-us/library/ms171728.aspx -------------------- Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог. Эвенгар Салладорский, основатель Школы Тьмы. |
|||
|
||||
![]() ![]() ![]() |
Прежде чем создать тему, посмотрите сюда: | |
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |