Потоки в VB .Net 2008
Dim Поток2 As New System.Threading.Thread(AddressOf Процесс_потока2)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Поток1.Start()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Поток2.Start()
End Sub
Private Sub Процесс_потока1()
Dim i As Integer = 1
Do
TextBox1.Text = i
Debug.WriteLine("Работает 1 поток:" & i)
i += 1
Loop
End Sub
Private Sub Процесс_потока2()
Dim i As Integer = 1
Do
TextBox2.Text = i
Debug.WriteLine("Работает 2 поток:" & i)
i += 1
Loop
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles But-ton3.Click
MsgBox("Привет!")
End Sub
А вот про безопасные потоки, про BeginInvoke, Invoke, EndInvoke поняять ни чего не могу. Нашел в инете несколько статей, но ниче не пойму, как обратиться к объекту безопаснор? помогите ссылкой с легким объяснением или сами плиз объясните....
if(lbl.InvokeRequired) {
lbl.Invoke(new ThreadStart(delegate {
SetLabelText(lbl, text);
}));
} else {
lbl.Text = text;
}
}
объясните шоль че такое делегат и вообоще строку lbl.Invoke(new ThreadStart(delegate {
SetLabelText(lbl, text);
плиз
if(lbl.InvokeRequired) {
lbl.Invoke(new ThreadStart(delegate {
SetLabelText(lbl, text);
}));
} else {
lbl.Text = text;
}
}
SetLabelText(lbl, text);
плиз
Доступ к свойствам компонента (по-умолчанию) ограничен потоком (thread), в котором он создан. Чтобы модифицировать значение свойства ли вызвать некоторый метод требуется выполнить синхронизацию потоков. Синхронизация достигается вызовом метода Invoke. В качестве параметра этот метод требует делегат - простыми словами, указатель на некоторую функцию.
Чтобы не создавать вспомогательный метод и не захламлять тем самым код класса (еще потребуется передавать туда значения!) я использовал анонимный метод (объявляется в теле метода через ключевое слово delegate) и обернул его в строго типизированную форму функции без параметров (тип делегата ThreadStart вполне подходит для этого, но потоки тут не создаются, уверяю вас) - этот цирк нужен для передачи в Invoke нашего анонимного метода.
Прощ говоря, я выполняю рекурсивный вызов той же самой функции SetLabelText с теми же параметрами, но уже в синхронизированном контексте.
Цель работы этой связки такая же как и Invoke.
Это просто асинхронный вариант вызова Invoke. Вообще XXX, BeginXXX, EndXXX можно увидеть во многих местах - это стандартный подход.
Дело в том, что Invoke блокирует работу текущего потока на время выполнения того делегата. Иногда это может занять отностильно много времени, потому чтобы избежать моментальной блокировки (например чтобы выполнить какие-то еще полезные действия) используют BeginInvoke. Можно сказать (на самом деле это несовсем так), что BeginInvoke создает новый поток исполнения, в котором выполняется оригинальный Invoke. Помимо этого BeginInvoke возвращает специальный объект типа IAsyncResult, который нужен для завершения асинхронной операции через EndInvoke. Какраз таки EndInvoke может блокировать текущий поток исполнения до завершения вызова делегата (если до вызова EndInvoke код делегата полностью выполнился, то, конечно, блокировки не будет).
Обычно эта связка используется так:
// какието действия
....
control.EndInvoke(async); // дожидаемся завершения инвоука
Вот уж не знаю. По хорошему этот вопрос входит в университетский курс операционных систем. Ищите на тему семафоров Дейкстры - это матчасть - на них в принципе строится любая синхронизация.
Dim Поток As New Threading.Thread(AddressOf Процесс_Потока)
Private Sub SetLabelText()
If lbl.InvokeRequired Then
lbl.Invoke(New Threading.ThreadStart(AddressOf SetLabelText))
Else
lbl.Text = "Text"
End If
End Sub
Private Sub Процесс_Потока()
SetLabelText()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Поток.Start()
End Sub
End Class
Все работает тип топ!
А если чисто перенести код с твоей платформы на мою, то не работает...:
Dim Поток As New Threading.Thread(AddressOf Процесс_Потока)
Private Sub SetLabelText()
If lbl.InvokeRequired Then
lbl.Invoke(New Threading.ThreadStart(delegate(SetLabelText(lbl, text))
Else
lbl.Text = "Text"
End If
End Sub
Private Sub Процесс_Потока()
SetLabelText()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Поток.Start()
End Sub
End Class
Подчекркивает
и пробовал ставить AddressOf b четока не делал - ерунда, не робит с параметрами че делать, поомогите,?
и пробовал ставить AddressOf b четока не делал - ерунда, не робит с параметрами че делать, поомогите,?
Наверное hardcase хотел сказать что ты должен сначала объявить делегат а потом его там использовать.
.
.
.
private void UpdateState(string value)
{
if (lbl.InvokeRequired)
{
lbl.Invoke(new UpdateLabelText(UpdateState), new object[] { value });
}
else
{
lbl.Text = value;
}
}
.
.
.
private void UpdateState(string value)
{
if (lbl.InvokeRequired)
{
lbl.Invoke(new UpdateLabelText(UpdateState), new object[] { value });
}
else
{
lbl.Text = value;
}
}
Вот, переделал под VB.Net, работает. Проверьте как правильно я понимаю. Статью еще не читал, которую последнюю мне дали...некогда пока....
Delegate Sub UpdateLabelText(ByVal text As String) ' Создаем делегат с именем UpdateLabelText и параметром text(нпонятно как то..) Делегат это ж ссылка н процуедуру? так где тут ссылка?
Private Sub UpdateState(ByVal value As String) 'Процедура UpdateState
If lbl.InvokeRequired Then 'Если объект требует синхронизации(т.е. он не порожден этим потоком), то
lbl.Invoke(New UpdateLabelText(AddressOf UpdateState), value) ' несовсем понятно...((Синхронизируем основной поток(где создан объект) с этим, передавая делегат(ссылку) рекурсивно(на эту же процедуру) и передаем этой прцедуре параметры в массиве( в данном случае один - value)
Else
lbl.Text = value 'Если объект поражден им(или уже синхронизированы потоки), то тупо меняем свойство
End If
End Sub
Private Sub процесс_потока()
UpdateState("проверка") ' Вызываем процедуру из потока
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Поток.Start() ' итак ясно...
End Sub
Да, верно понимаешь ;)
В той строке ты не создаешь делегат. Ты его объявляешь. Т.е. сообщаешь компилятору что сущесвтует некоторое семейство методов (Sub-рутин) UpdateLabelText с одним параметром типа строка.
А создаешь конкретный экземпляр делегата вот этой строкой:
New UpdateLabelText(AddressOf UpdateState)
P.S. Плюсик ставится нажатием на весы слева от сообщения, под аватарой.
P.S. Уже полоина клавиш на клаве плохо работают, так что простите за очепятки;)
Да, объект Thread - одноразовый. Для создания экземпляра объекта уходит совсем мало времени (стремится к нулю). Относительно долго выполняется метод Start - но это издержки архитектуры NT. Для частого и быстрого создания потоков управления существует пул потоков: ThreadPool. Эта ситемная структура содержит конечное количество потоков (обычно достаточное для настольного приложения) и позволяет быстро создавать нитку.