2017-01-11 1 views
0

Я хочу обновить метку во время цикла foreach.Изменить текст метки в цикле foreach

Проблема заключается в следующем: программа ждет, пока цикл не будет завершен, а затем обновит метку.

Возможно ли обновление метки во время цикла foreach?

Код:

Dim count as Integer = 0 
For Each sFile as String in Files 
    'ftp-code here, works well 
    count = count+1 
    progressbar1.value = count 
    label1.text = "File " & count & " of 10 uploaded." 
next 

Заранее спасибо

+0

Вы пробовали этот код? Каков был результат? – ADyson

+0

Ответ: да. Хотя сначала вы должны были попробовать, так как вы ответили бы на свой вопрос. –

+0

Он делает, но я предполагаю, что вы хотите увидеть, как он отражается, поскольку он обновляется, а не замораживается пользовательский интерфейс? Это проблема? – Bugs

ответ

2

Ярлык не обновляется, поскольку UI поток блокируется во время выполнения вашего foreach цикла.
Вы можете использовать async-await подход

Private Async Sub Button_Click(sender As Object, e As EventArgs) 
    Dim count as Integer = 0 
    For Each sFile as String in Files 
     'ftp-code here, works well 
     count = count+1 

     progressbar1.value = count 
     label1.text = "File " & count & " of 10 uploaded." 

     Await Task.Delay(100) 
    Next 
End Sub 

Потому что вы будете работать с Ftp соединений, что является идеальным кандидатом для использования async-await.

Линия Await освободит поток пользовательского интерфейса, который обновит метку новым значением и продолжит работу с этой строки через 100 миллисекунд.

Если вы будете использовать асинхронный код для FTP соединения, то вам не нужно Task.Delay

+0

Моя программа не распознает 'Задача'. Есть ли еще какие-то вещи, которые я должен знать? Может быть, я просто неправильно понял, что вы имеете в виду. – neverlucky

+1

Вам нужна ссылка на 'System.Threading.Tasks' – Fabio

0

Вы уже приняли ответ, но только в качестве альтернативы BackgroundWorker также может использоваться для чего-то вроде этого. В моем случае FTP для получения исходных файлов происходит очень быстро, поэтому этот фрагмент из события DoWork предназначен для загрузки этих файлов на принтер.

Dim cnt As Integer = docs.Count 
Dim i As Integer = 1 
For Each d As String In docs 
    bgwTest.ReportProgress(BGW_State.S2_UpdStat, "Downloading file " & i.ToString & " of " & cnt.ToString) 

    Dim fs As New IO.FileStream(My.Application.Info.DirectoryPath & "\labels\" & d, IO.FileMode.Open) 
    Dim br As New IO.BinaryReader(fs) 
    Dim bytes() As Byte = br.ReadBytes(CInt(br.BaseStream.Length)) 

    br.Close() 
    fs.Close() 
    For x = 0 To numPorts - 1 
     If Port(x).IsOpen = True Then 
      Port(x).Write(bytes, 0, bytes.Length) 
     End If 
    Next 
    If bytes.Length > 2400 Then 
     'these sleeps are because it is only 1-way comm to printer so I have no idea when printer is ready for next file 
     System.Threading.Thread.Sleep(20000) 
    Else 
     System.Threading.Thread.Sleep(5000) 
    End If 

    i = i + 1 
Next 

В случае ReportProgress ... (конечно, вам необходимо установить WorkerReportsProgress свойство True)

Private Sub bgwTest_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwTest.ProgressChanged 

    Select Case e.ProgressPercentage 
     'BGW_State is just a simple enum for the state, 
     'which determines which UI controls I need to use. 
     'Clearly I copy/pasted from a program that had 15 "states" :) 
     Case BGW_State.S2_UpdStat 
      Dim s As String = CType(e.UserState, String) 
      lblStatus.Text = s 
      lblStatus.Refresh() 

     Case BGW_State.S15_ShowMessage 
      Dim s As String = CType(e.UserState, String) 
      MessageBox.Show(s) 

    End Select 

End Sub 
-1

Разве это не достаточно, чтобы использовать Application.DoEvents()? Это очистит сборку, и вы сможете очень быстро увидеть текстовые поля.

+0

[Is DoEvents Evil?] (Https://blog.codinghorror.com/is-doevents-evil/), также [Использование Application.DoEvents()] (http : //stackoverflow.com/a/5183623/1115360). –