나사산로드 (대기) 화면
-
11-07-2019 - |
문제
긴 작업 중에 대기 스크린을 구현하는 일반적인 방법을 찾고 있습니다. 나는 몇 번 전에 스레드를 사용했지만, 나는 그것을 매우 가난하거나 너무 번거 로움 (그리고 복사/붙여 넣기 - 공포!)으로 구현했다는 느낌이 들었습니다.
나는 이것을 가능한 한 일반적이고 단순하게 유지하고 싶기 때문에로드를 구현할 필요가 없습니다. BackgroundWorker
모든 종류의 쓰레기를 처리하여 유지하기가 어렵습니다.
여기에 내가하고 싶은 일이 있습니다. 이것은 실제로 가능한/모범 사례/uthing과 다를 수 있습니다 - vb.net, framework 2.0 (익명 방법 없음)을 사용합니다.
Private Sub HandleBtnClick(sender as Object, e as EventArgs) Handles Button.Click
LoadingScreen.Show()
'Do stuff here, this takes a while!'
Dim Result as Object = DoSomethingTakingALongTime(SomeControl.SelectedObject)
LoadingScreen.Hide()
ProcessResults(Result)
End Sub
응용 프로그램은 이제 완전히 단일 스레드이므로 모든 것이 GUI 스레드에서 실행됩니다. 객체에 액세스 할 수 있어야합니다 DoSomethingTakingALongTime()
크로스 스레드 예외를 얻지 않고. GUI 스레드는 완료하는 데 몇 가지 방법 (오랜 시간이 걸리는)을 기다립니다. LoadingScreen
양식은 반응 형을 유지해야합니다 (애니메이션/진행 상황이 있습니다).
이것은 가능한/좋은 접근 방식입니까, 아니면 이런 식으로 너무 단순한 것을보고 있습니까? 이 문제에 관한 모범 사례는 무엇입니까? 그리고 가장 중요한 것은 어떻게 그러한 시스템을 구현할 수 있습니까? 내가 이미 언급했듯이, 나는 나사산에 대한 경험이 거의 없으므로 부드럽게 해주세요 :-)
해결책
문제는 작업자 스레드 데이터를 UI 스레드로 전달하려고 할 때 크로스 스레드 예외를 얻는 것입니다. 당신이해야 할 일은 UI에서 컨트롤을 설정하기 전에 invokequired 및 beginvoke를 점검하여 다음과 같은 오류를 얻지 못하는 것입니다.
Private Sub work_CrossThreadEvent(ByVal sender As Object, ByVal e As System.EventArgs) Handles work.CrossThreadEvent
If Me.InvokeRequired Then
Me.BeginInvoke(New EventHandler(AddressOf work_CrossThreadEvent), New Object() {sender, e})
Return
End If
Me.Text = "Cross Thread"
End Sub
그냥 변경하십시오 New EventHandler
사용하는 이벤트 처리기에 참여하십시오.
또한 배경 작업자를 사용하는 것은 작업자 수업에 나쁜 방법이 아니라고 생각합니다. 작업을위한 수업을 만들고 백그라운드 작업자를 사용하여 스레딩 작업을 조금씩 수행합니다.
Public MustInherit Class Worker
Protected WithEvents worker As BackgroundWorker
Public Sub New()
worker = New BackgroundWorker()
worker.WorkerReportsProgress = True
worker.WorkerSupportsCancellation = True
End Sub
Public Sub Start()
If (Not worker.IsBusy AndAlso Not worker.CancellationPending) Then
worker.RunWorkerAsync()
End If
End Sub
Public Sub Cancel()
If (worker.IsBusy AndAlso Not worker.CancellationPending) Then
worker.CancelAsync()
End If
End Sub
Protected MustOverride Sub Work()
Private Sub OnDoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork
Work()
End Sub
Public Event WorkCompelted As RunWorkerCompletedEventHandler
Private Sub OnRunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted
OnRunWorkerCompleted(e)
End Sub
Protected Overridable Sub OnRunWorkerCompleted(ByVal e As RunWorkerCompletedEventArgs)
RaiseEvent WorkCompelted(Me, e)
End Sub
Public Event ProgressChanged As ProgressChangedEventHandler
Private Sub OnProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles worker.ProgressChanged
OnProgressChanged(e)
End Sub
Protected Overridable Sub OnProgressChanged(ByVal e As ProgressChangedEventArgs)
RaiseEvent ProgressChanged(Me, e)
End Sub
End Class
Public Class ActualWork
Inherits Worker
Public Event CrossThreadEvent As EventHandler
Protected Overrides Sub Work()
'do work here'
WorkABit()
worker.ReportProgress(25)
WorkABit()
worker.ReportProgress(50)
WorkABit()
worker.ReportProgress(75)
WorkABit()
worker.ReportProgress(100)
End Sub
Private Sub WorkABit()
If worker.CancellationPending Then Return
Thread.Sleep(1000)
RaiseEvent CrossThreadEvent(Me, EventArgs.Empty)
End Sub
End Class
면책 조항 .. VB와 비트 레슬러리는하지만 아이디어를 얻어야합니다.
다른 팁
스레드에서 application.run (yourform)을 사용하여 원하는 것을 얻으십시오.
어떻게 든 닫기 위해 양식에 신호를 보내야합니다.
나는 당신이 도움이되지 않는 것을 찾지 않기를 바랍니다. 그러나 나는 왜 당신이 스레드 대기 화면을 원하는지 의문을 제기 할 것입니까? 먼저 스레딩을 사용하는 이유는 UI가 반응이 유지되고 긴 작업이 백그라운드에서 수행되기 때문입니다.
그렇지 않으면 Formloading Control에 진행 상황이있을 수 있으며 정기적으로 업데이트 할 수있는 DOMETHINGOMETINGTAMETINGTAMEND가 있습니다. 이것은 스레드가 전혀 필요하지 않습니다.