장시간 독자, 처음 포스터. 보통 나는 대답을 찾아서 작동시킬 수 있습니다. 이번에는 ..... 저는 VS2013에서 VB.NET을 사용하고 있습니다. 보조 스레드에서 수행 한 작업으로 진행률 표시 줄을 업데이트하려고합니다. 알았어? 아니, 더 복잡하게 만들어야 했어. 진행률 표시 줄 (ToolStripProgressBar1)은 프로젝트의 MDI 인 기본 폼 (frmMain)에 있습니다. 보조 양식 (frmShipping)에는 클래스의 일부 COMM 포트 통신을 수행하는 두 번째 스레드를 시작하는 버튼이 있습니다 (cApex). 업데이트 진행률 막대를 frmMain 메인 UI 스레드 (frmShipping 버튼)에서 가져올 수 있습니다. 모든 위대한 작품을vb.net 업데이트 진행률 표시 줄 다중 스레드
Private Sub btnreadScanner_Click(sender As Object, e As EventArgs) Handles btnreadScanner.Click
Dim thrReadScanner As New System.Threading.Thread(AddressOf ReadScanner)
thrReadScanner.IsBackground = True
thrReadScanner.Start()
End Sub
Private Sub ReadScanner()
Dim strRowCount As String
ShipmentMsg(2)
strRowCount = objShipping.RecordsExisit.ToString()
Try
objApex.ImmediateMode()
If objApex.FileDownload = False Then
Throw New Exception(Err.Description)
End If
Catch ex As Exception
ShipmentMsg(1)
MessageBox.Show("No Data downloaded from Scanner. Try Again. Error#: " & Err.Number & " : " & Err.Description)
Exit Sub
End Try
RecordCount()
DataGridUpdate()
btnProcessShipment.Enabled = True
ShipmentMsg(5)
ScanErrors()
End Sub
이 :
이 frmShiping 버튼의 코드와 멀티 스레드 절차입니다. 예상대로. objApex.FileDownloadcApex의 호출은 진행률 표시 줄을 (실제로 FileDownload에서 호출 한 다른 함수에서) 업데이트 할 위치입니다. 여기에 코드가 있습니다.
Try
GetHeaderRecord()
If Count <> 0 Then intTicks = Math.Round((100/Count), 1)
For intcount As Integer = 1 To Count
Dim intLength As Integer = Length
Do While intLength > 0
literal = Chr(_serialPort.ReadChar.ToString)
If literal = ">" Then Exit Do
strRecord = strRecord & literal
intLength = intLength - 1
Loop
REF = strRecord.Substring(0, 16).TrimEnd
SKID = strRecord.Substring(16, 16).TrimEnd
REEL_BC = strRecord.Substring(32, 15).TrimEnd
ScanDate = strRecord.Substring(47, 8).TrimEnd
ScanDate = DateTime.ParseExact(ScanDate, "yyyyMMdd", Nothing).ToString("MM/dd/yyyy")
ScanTime = strRecord.Substring(55, 6).TrimEnd
ScanTime = DateTime.ParseExact(ScanTime, "HHmmss", Nothing).ToString("HH:mm:ss")
strRecordTotal = strRecordTotal & strRecord & CRLF
Dim strSQL As String
strSQL = "INSERT INTO tblScanData (PONo,Barcode,SkidNo,ScanDate,ScanTime) " & _
"VALUES (" & _
Chr(39) & REF & Chr(39) & _
"," & Chr(39) & REEL_BC & Chr(39) & _
"," & Chr(39) & SKID & Chr(39) & _
"," & Chr(39) & ScanDate & Chr(39) & _
"," & Chr(39) & ScanTime & Chr(39) & ")"
objData.Executecommand(strSQL)
strRecord = ""
Next
마지막으로 진행률 표시 줄을 업데이트하는 방법입니다.
Dim f As frmMain = frmMain
System.Threading.Thread.Sleep(100)
DirectCast(f, frmMain).ToolStripProgressBar1.PerformStep()
정말 PerformStep을 For 루프에 넣어야합니다. 루프를 돌 때마다 진행률 막대를 단계별로 계산하여 막대를 공정하게 정확하게 만드는 데 필요한 단계의 비율을 계산합니다 (루프 이전의 수학 코드로 완료). 또한 진행률 표시 줄 컨트롤의 속성을 frmMain에 설정했습니다. 그래서 나는 미쳐 있습니까? 아니면 이것을 성취 할 수있는 방법이 있습니까? 나는 위임자를 사용하여 시도했다. Me.Invoke (New MethodInvoker (AddressOf pbStep)) 코드를 스레드로부터 안전하게 보호합니다. 크로스 스레드 호출에 대해서는 오류가 발생하지 않지만 진행률 표시 줄은 업데이트되지 않습니다. 미안하지만 길다.하지만 나는 길을 잃고 내 ADHD는이 아이디어를 폐기하지 못하게 할 것이다.
편집은 AS 요청한 :
Public Sub pbStep()
Dim f As frmMain = frmMain
If Me.InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf pbStep))
Else
DirectCast(f, frmMain).ToolStripProgressBar1.PerformStep()
System.Threading.Thread.Sleep(100)
End If
End Sub
코드의 어느 부분이'pbStep'입니까? 아직 표시되지 않은 경우 표시해야합니다. – TyCobb
이것은 표준 VB.NET 트랩입니다. frmMain은 개체 참조가 아니라 형식 이름입니다. 스레드에서 사용하면 frmMain의 * new * 인스턴스가 생깁니다. 표시되지 않습니다. Show() 메서드는 호출되지 않았습니다. 반창고는 'Dim f'를 Else 절로 이동시키는 것입니다. 100msec 동안 잠자는 것은 거의 이해가되지 않습니다. 진행률을 계산할 수 없다면 진행률 막대를 Style = Marquee와 함께 사용하십시오. BackgroundWorker를 사용하면 이러한 트랩을 피할 수 있습니다. –
한스 - 귀하의 통찰력이 정확했습니다. 'f.Show'는 폼에 포커스를두고 진행 막대를 보았고 예상대로 수행했습니다. 진실은 이것이 내가 어떻게 작동하기를 원하지 않는가라는 것입니다. 내가 속일 수있는 걸 보게 될거야. 아래 James 제안은 BackgroundWorker도 사용합니다. BGW를 사용하기 위해 코드를 다시 작성하는 것에 반대하지는 않을 것입니다. 그러나 나는 그들에 대한 것이고, 그들이 내 상황에서 어떻게 작동 할 것인지 모릅니다. 위의 코드에 대한 제안 사항 (코드 작성을 요구하는 것이 아니므로 지시 사항을 이해하는 데 도움이됩니다). – Mckenzie