Почему моя тема не запускается сразу? - PullRequest
4 голосов
/ 04 октября 2010

см. Программу ниже.Я начинаю новый поток x с помощью функции abc, затем выполняю более длинную задачу.Почему x начинается только после end sub?Разве это не должно начаться сразу, перед сном?

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim x As New Threading.Thread(AddressOf abc)
        x.SetApartmentState(Threading.ApartmentState.MTA)
        x.Start()

        System.Threading.Thread.Sleep(5000)
    End Sub





Sub abc()
    For i As Integer = 0 To 10 Step 1
        Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )"
        'Me.StatusStrip1.Invoke(
        MsgBox(i.ToString)
        System.Threading.Thread.Sleep(1000)
    Next
End Sub

Редактировать: Решение заключается в следующем:

(A) Поместите как попытки подключения, так и обратный отсчет времени в отдельные потоки.(B) Обновите интерфейс следующим образом:

    If Me.InvokeRequired Then
        Me.Invoke(pUpdateStatusMessage, "Successfully connected.")
    Else
        UpdateStatusMessage("Successfully connected.")
    End If

С этим объявленным глобально, поэтому передача аргументов не требуется:

Delegate Sub t_pUpdateStatusText(ByVal strMessage As String)
Public pUpdateStatusMessage As t_pUpdateStatusText = New t_pUpdateStatusText(AddressOf UpdateStatusMessage)

Public Sub UpdateStatusMessage(ByVal strMessage As String)
    Me.lblStatus.Text = strMessage
    Me.StatusStrip1.Update()
End Sub

Ответы [ 4 ]

9 голосов
/ 04 октября 2010

Функция abc действительно запустится до завершения метода Button1_Click. Причиной путаницы являются 2 вещи

Во-первых, вы напрямую обновляете пользовательский интерфейс из фонового потока со следующей строкой

Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )" 

Этот код неверен и может вызвать проблемы позже. Вы должны использовать вызов Invoke для фактического изменения пользовательского интерфейса. Как вы делаете во второй строке, которая подводит нас к следующей проблеме.

Вызов Invoke является синхронным. Он работает, по сути, помещая сообщение в очередь сообщений Windows и ожидая его обработки перед возвратом. Вызов Thread.Sleep, который вы добавили в основной поток, не позволяет запустить очередь сообщений. Это эффективно останавливает фоновый поток до тех пор, пока не завершится вызов Sleep, создавая впечатление, что фоновый поток не запущен.

2 голосов
/ 04 октября 2010

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

0 голосов
/ 05 октября 2010

Возможно, это не относится к вашему вопросу, но для обновления пользовательского интерфейса из отдельного потока я предлагаю вам использовать BackgroundWorker.поместите функцию abc () в DoWork и используйте ProgessChanged для обновления пользовательского интерфейса.

0 голосов
/ 05 октября 2010

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

Примерно так:

private delegate void ControlUpdateTextHandler(TextBox ctrl, string text);
public void UpdateControlText(TextBox ctrl, string text)
{
    if (ctrl.InvokeRequired)
    {
        ctrl.BeginInvoke((ControlUpdateTextHandler)UpdateControlText, ctrl, text);
    }
    else
        ctrl.Text = text;
}

Должно работать, если он вызывается из «правильного» потока (поскольку InvokeRequired будет ложным, если он вызывается потоком, которому принадлежит элемент управления), простообновление текста или из «неправильного» потока (поскольку InvokeRequired будет иметь значение true, если вызывается из другого потока), путем постановки в очередь вызова, выполняемого потоком пользовательского интерфейса.

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