2010-10-04 26 views
5

aşağıdaki programa bakınız. Yeni bir iş parçacığı x işlev abc ile başlatıyorum, daha sonra biraz daha görev yapıyorum. Neden x sadece sondan sonra başlıyor? Uyumadan hemen önce başlamamalı mı? İplerim neden hemen başlamıyor?

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 



Düzenleme:

(A) bağlantı girişimlerini ve ayrı parçacıkları halinde zaman aşımı sayım hem koyun:
çözeltisi budur.
(B) böyle UI Güncelleme: Sen bir sivil adresinin UI güncelliyoruz

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 
+0

İş parçacığının yalnızca yöntem bittikten sonra başladığını nasıl doğrularsınız? Etikete mi bakıyorsunuz yoksa ateş etmeyi mi bırakıyorsunuz? –

+0

Aslında, görüntülemediğinde, bir kesme noktası belirledim. –

cevap

10

abc işlevi gerçekten Button1_Click yönteminin sona ermesinden önce başlayacaktır. Ne karışıklığa neden olan ilk doğrudan aşağıdaki satırı

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

Bu kod yanlış ve daha sonra sorunlara neden olabilir bir arka plan iplikten UI güncelliyoruz olmasıdır 2 şey

olduğunu. UI'yi gerçekten değiştirmek için Invoke çağrısını kullanmalısınız. Bizi bir sonraki probleme getiren ikinci satırda yaptığınız gibi.

Invoke numaralı çağrı senkronize. Windows ileti kuyruğuna bir ileti göndermeye ve geri dönmeden önce işlenmesini beklemeye çalışır. Ana iş parçacığına eklediğiniz Thread.Sleep çağrı, ileti sırasının gerçekten çalışmasını engeller. Bu, arka plan iş parçacığının çalışmadığı görünümü vererek Sleep çağrısı tamamlanıncaya kadar arka plan iş parçacığını etkin bir şekilde bekler.

2

: Bununla

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

küresel hiçbir argüman geçirme gereklidir, ilan UI iş parçacığı. Bu izin verilmez ve garip davranışlara yol açabilir. Gecikme davranışına sebep olan şey bu mu, bilmiyorum, ama önce bunu çözmen gerekecek.

0

Başkalarının söylediklerine eklemek için, denetim güncelleştirmesi gereksinimlerinizin imzasını tanımlamak üzere bir temsilci oluşturabilirsiniz (bu durumda, metin kutusu ve dizeyi varsayıyorum, ancak gereksinim duyulabilecek ancak bunlar tanımlanabilir) ve Ardından, gerektiğinde kendini yinelemeli olarak kendisini çağrıştıran temsilci imzasını izleyen bir yöntem oluşturun. Böyle

şey:

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; 
} 

basitçe metni güncelleyerek (bu denetimi sahibi parçacığı tarafından çağrılırsa InvokeRequired yanlış olacaktır çünkü) bunun "doğru" iplikten denir eğer işe halinde, veya "yanlış" iş parçacığından (farklı bir iş parçacığından çağrılırsa InvokeRequired değeri doğru olur), UI iş parçacığı tarafından gerçekleştirilecek çağırmayı sıraya alarak.

0

Sorunuzla ilgisi olmayabilir, ancak kullanıcı arabirimini ayrı bir iş parçacığından güncellemek için BackgroundWorker'ı kullanmanızı öneririm. DoWork'ta abc() işlevini yerleştirin ve UI'yi güncellemek için ProgessChanged'ı kullanın.

İlgili konular