Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование метода Invoke 
:(
    Опции темы
RUVATA
Дата 22.2.2011, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



Всем доброго времени суток...
В процессе освоения платформы плавно перешел к программированию многопоточного приложения, благо Vb.NET теперь это умеет
среда Visual Studio 2010
Доступный пример нашел здесь но он не отрабатывает, 
Код

Imports System.Threading
Imports VB = Microsoft.VisualBasic

Public Class TestTheding
    Inherits System.Windows.Forms.Form
    Dim Thread1 As Thread

    Private Sub SleepVBNET()
        Dim Seconds As Integer = 10
        ' процедура ожидания 10 сек
        Dim Start As Integer
        Start = VB.Timer
        ' ожидание в цикле
        Do While VB.Timer < Start + Seconds
            Label1.Text = "Текущее время = " & VB.TimeOfDay
        Loop
        ' Label1.Text = "Процесс завершен"
    End Sub

    Private Sub ButtonStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonStart.Click
        ' запуск параллельного потока
        Thread1 = _
         New Thread(AddressOf SleepVBNET)
        Thread1.Start()
    End Sub

    Private Sub ButtonAbort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAbort.Click
        ' аварийное завершение потока
        Thread1.Abort()
    End Sub
End Class

на выходе имею ошибку
а именно 
Код

Label1.Text = "Текущее время = " & VB.TimeOfDay

не обрабатывается по причине
"Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'Label1' не из того потока, в котором он был создан."
Надо мол использовать Invoke
А ВОТ КАК ? 
Я наскоком на справку понять не смог... 
прошу помощи коллективного разума 
Можно мне подсказать как на этом примере использовать эту безопасную многопоточность.



Это сообщение отредактировал(а) RUVATA - 22.2.2011, 15:26
PM MAIL   Вверх
-Mikle-
Дата 22.2.2011, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 4
Всего: 59



Код

this.Invoke((Action)delegate
{
    // код для доступа к элементам окон
});


Код внутри бресетов выполнится в основном потоке приложения. Имейте ввиду, что пока выполняется метод Invoke, ваш поток будет ждать отработки. Если вы не желаете, чтоб ваш поток ждал выполнения кода для окна, то используйте метод BeginInvoke.

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


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
RUVATA
Дата 24.2.2011, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



Все равно, не понял... 
Я уже какие только примеры не пробовал, они даже синтаксическую проверку не проходят...
Можно попросить вас описать конструкцию, принципал... 

Вот допустим есть основной поток "Основной" в котором описана форма, с элементом управления "Кнопка"
Есть дополнительный поток "ВторПоток
Я хочу из "ВторПоток" изменять некое свойство объекта "Кнопка"
Такое действие само по себе не является потокобезопасным (бред Microsoft)
(в Swing Java такого геморроя нет, чтобы избежать взаимоблокировки или гонки там используются конструкции очереди потипо Try Cath с условием)
и дабы разрешить возможные конфликты совместного доступа, предлагается на выбор:
или сконструировать "ВторПоток" изначально специфическим BackgroundWorker , я еще не пробовал...
или использовать специальный метод вхождения в основной поток Invoke...
Но его суть я так и "нераскурил", какой делегат, кто он smile , куда его, где собственно сам вызов и т.д.
Пример из справки просто тащит, т.к. он сам на этом-же исключении тормозит smile

Это сообщение отредактировал(а) RUVATA - 24.2.2011, 09:14
PM MAIL   Вверх
jonie
Дата 24.2.2011, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Цитата(RUVATA @  24.2.2011,  09:13 Найти цитируемый пост)

Но его суть я так и "нераскурил", какой делегат, кто он smile , куда его, где собственно сам вызов и т.д.

делегат - это прокаченный указатель на функцию. Т.е. вы в Invoke() передаете указание "что делать". Invoke же ставит это "указание что делать" в оконную очередь на выполнение - winAPI функция SendMessage. Ф-я SendMessage является блокирующей и производит постановку сообщения в очередь Windows окна сообщений (стандартная оконнная очередь сообщений).

Далее, каждое окно (точнее процесс который создал окно) в системе Windows производит следующие нехитрые действия (чтобы окно не "зависло" и вообще как-то реагировало на юзера):
Код

   MSG stMsg = { 0 };
   while( PeekMessage( &stMsg, hWnd_i, 0, 0, PM_REMOVE ))
   {
       TranslateMessage( &stMsg );
       DispatchMessage( &stMsg );
    }


Это так называемая оконная процедура. Она работает в том же потоке (пока окно не будет уничтожено вызовом DestroyWindow()) что и создавалось окно. И это важное замечание.

Этот цикл производит ничто иное как прокачку (pumping) оконных сообщений непосредственно в процедуру (посредством вызова этой процедуры внутри функции DispatchMessage) обработки оконных сообщений окна, которая выглядит как-то так:
Код

DWORD __stdcall WndProc(HWND hWnd, MSG message, DWORD wParam, DWORD lParam) {
switch (message)
{
        case сообщение_о_выполнении_делегата:
              исполнить_делегат();
        break;
.....
        default:
            //пусть винда сама разбирается что делать
            return DefWindowProc(hWnd, message, wParam, lParam);
}
}


Т.о. получается что ваш делегат (а это указатель на метод, не забываем) будет вызываться в потоке в котором создано окно и не сможет нарушить целостность данных (многопоточная запись в shared ресурс), как это мог бы сделать при многопоточном доступе.

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


Такие дела.

Я, конечно, не особо уверен что обстоят дела именно так, но это моё мнение...

Это сообщение отредактировал(а) jonie - 24.2.2011, 10:10


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
RUVATA
Дата 24.2.2011, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



Цитата

Т.е. вы в Invoke() передаете указание "что делать".

Ну так и я так думал до определенной сотой попытки подпихнуть что ни будь типа
Код

Label1.Invoke(Label1.text = "бла-бла-бла")

ну так нет-же в аргумент нужен объект типа System.Delegate
справка описывает его так 
"Представляет делегат — структуру данных, указывающую на статический метод или на экземпляр класса и метод экземпляра этого класса."
Ну во первых меня сильно долбит изобилие термина МЕТОД... мне-то нужно обратиться к СВОЙСТВУ... но не суть...
мне-бы банальный пример...
КАК ОБРАТИТЬСЯ ЧЕРЕЗ Invoke К СВОЙСТВУ ЭЛЕМЕНТА UI-ПОТОКА Label1.Text ИЗ ДОЧЕРНЕГО ПОТОКА
PM MAIL   Вверх
diadiavova
Дата 24.2.2011, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 18
Всего: 142



Цитата(RUVATA @  24.2.2011,  10:24 Найти цитируемый пост)
Ну во первых меня сильно долбит изобилие термина МЕТОД... мне-то нужно обратиться к СВОЙСТВУ... 

Методу Invoke надо в качестве аргумента передать метод. Если тебе нужно обратиться к свойству, то сделать это можно в передаваемом методе. То есть ты либо определяешь этот метод отдельно и передаешь на него ссылку
Код

Sub AddLabelText()
    Label1.Text = "блаблабла"
End Sub

После чего делаешь так
Код

Label1.Invoke(AddressOf AddLabelText)


Либо определяешь метод прямо в коде вызова
Код

Label1.Invoke(Sub() Label1.text = "бла-бла-бла")



Это сообщение отредактировал(а) diadiavova - 24.2.2011, 11:11


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
RUVATA
Дата 24.2.2011, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



diadiavova, Огромное спасибо, выручаешь уже не первый раз...
Я вот только сейчас "прозрел" на счет того что имеется  в виду как МЕТОД... 
Может я и не прав, но по моему это наводит путаницу... потому что это не МЕТОД (чей-же это метод UI-потока что ли? где базовый объект) в понимании ООП... это не что иное как ПРОЦЕДУРА вернее её экземпляр,
причем мне не понятно зачем этот наворот, неужели абстрактный  Sub () нельзя было включить в сам Invoke, а для извращений сделать отдельную перегрузку
и передавать собственно само обращение...
Просто лично меня МЕТОД вывел из рановесия... что за метод, чей, причем здесь метод вашпе... 
еще раз спасибо... 


Это сообщение отредактировал(а) RUVATA - 24.2.2011, 11:06
PM MAIL   Вверх
diadiavova
Дата 24.2.2011, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 18
Всего: 142



Цитата(RUVATA @  24.2.2011,  11:04 Найти цитируемый пост)
потому что это не МЕТОД (чей-же это метод UI-потока что ли? где базовый объект) в понимании ООП... это не что иное как ПРОЦЕДУРА вернее её экземпляр

Сейчас в основных языках платформы очень много наворотов из ФЯ и их становится все больше. Не вижу в этом проблемы, по-моему это благо. Что касается терминологии, то она оопэшная только и всего. Работа с делегатами только поначалу кажется сложной, со временем разберешься  и станет трудно без них обходиться. smile 
Цитата(RUVATA @  24.2.2011,  11:04 Найти цитируемый пост)
причем мне не понятно зачем этот наворот, неужели абстрактный  Sub () нельзя было включить в сам Invoke

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


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0747 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.