如何在没有"冻结"的情况下创建一个连续更新的表单。窗口

时间:2016-03-17 12:44:32

标签: vb.net forms

好的,所以我正在尝试创建一个小的VB.NET程序,它应用并监视另一个应用程序中的值,我遇到了一个我似乎无法找到答案的障碍。

我想要一个单独的表格,或者同一表格的一部分,从其他程序拉出值[不是问题]分析它们并显示它们的状态。问题是,每当我使用表单来实现这一点时,我发现这个更改文本所在的窗口在功能上对用户没有响应,鼠标滚轮旋转,并且无法访问位于该表单上的任何控件(其他按钮,最小化关闭,或点击将其带到前面/调整窗口大小的能力)。

我目前正在使用一个后台工作程序,它有一个显示表单的dowork方法,然后更新其上的文本标签,然后在循环中刷新表单。可以通过更改公共共享变量来取消此循环。我可以清楚地看到文本正在使用值进行更新,但是表单没有响应。

这有什么办法吗?我希望表单能够像常规应用程序窗口一样运行,并且在显示真实时可以调整大小/可关闭。

以下是我的代码示例,其中包含可能存在损害的位或其他编辑内容:

Imports System.ComponentModel
Imports System.Linq

Public Class Form1
    Public Shared notbroken = 1 'Break the killer loop

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Ok Button

        Button1.Hide() 'Stop user from clicking the button again.

        Dim choice

        'show which button is selected in each case
        Dim regenType As RadioButton = GroupBox1.Controls.OfType(Of RadioButton).FirstOrDefault(Function(r) r.Checked = True)
        Dim regenVariant As RadioButton = moving.Controls.OfType(Of RadioButton).FirstOrDefault(Function(r) r.Checked = True)

        'Assigns a number from the selection to these once the ok button is pressed.

        mainmethod(choice)

    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        notbroken = 0

        If BackgroundWorker1.WorkerSupportsCancellation = True Then
            BackgroundWorker1.CancelAsync()
        End If

    End Sub

    Private Sub mainmethod(regenchoice As Integer)
        'Main Logic
        'Project.Online = True 'TODO - Uncomment

        AssignHandles()

        CollectOrRestore("collect") 'Collect values to restore upon reopen

        'Recorder.Start

        RunRegen(regenchoice)

        If Not BackgroundWorker1.IsBusy = True Then
            BackgroundWorker1.RunWorkerAsync()
        End If

        'SaveRecording

        'CloseProj()

    End Sub


    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As  System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Form3.Show()

        Do While Form1.notbroken
            Form3.Label1.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")

            ' Sample of how Im reporting status
            Form3.Label2.Text = "Text String: " & statusOfTextStringCheck() 

            Form3.Refresh()
        Loop
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        If e.Cancelled = True Then
            Label1.Text = "Canceled!"
            Refresh()
            Threading.Thread.Sleep(2000)
            Label1.Text = "IN CASE OF EMERGENCY: "
            Form3.Close()
            Button1.Show()
            Return
        ElseIf e.Error IsNot Nothing Then
            Label1.Text = "Error: " & e.Error.Message
            Refresh()
            Threading.Thread.Sleep(2000)
            Label1.Text = "IN CASE OF EMERGENCY:"
            Form3.Close()
            Button1.Show()
            Return
        Else
            Label1.Text = "Done!"
            Refresh()
            Threading.Thread.Sleep(2000)
            Label1.Text = "In Case Of EMERGENCY:" & e.Result
            Form3.Close()
            Button1.Show()
            Return
        End If
    End Sub

    Private Sub CloseProj()
        Dim x = MsgBox("Are you sure you want to close the project?" & vbCrLf & ":Initial Values will be restored.", 65, "ClearVision")
        If x = 2 Then Return
        CollectOrRestore("restore") 'Restore Initial Values
        release()
        Me.Close()
    End Sub
End Class

1 个答案:

答案 0 :(得分:0)

这里我汇总了一个如何在表单中使用Background worker的快速示例。第一条规则不是在后台工作程序中设置任何UI元素,而是通过Background工作程序的ProgressChanged事件发送更改,并在UI线程上进行更改。

示例代码:

Public Class Form1
    Private Sub cmdStart_Click(sender As Object, e As EventArgs) Handles cmdStart.Click

        If Not BackgroundWorker1.IsBusy Then

            BackgroundWorker1.WorkerReportsProgress = True
            BackgroundWorker1.WorkerSupportsCancellation = True
            BackgroundWorker1.RunWorkerAsync()

        End If


    End Sub

    Private Sub cmdEnd_Click(sender As Object, e As EventArgs) Handles cmdEnd.Click
        _bCancel = True
    End Sub

    Private _bCancel As Boolean = False

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        Dim iIteration As Long = 0
        Do Until _bCancel
            iIteration += 1
            Dim sTime As String = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")
            Dim sStatus As String = "Iteration Status " & iIteration.ToString()
            BackgroundWorker1.ReportProgress(0, New WorkProgress(sTime, sStatus))
            Threading.Thread.Sleep(50)
        Loop


    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

        If Me.InvokeRequired Then
            Dim act As Action(Of System.ComponentModel.ProgressChangedEventArgs) = AddressOf HandleProgressChanged
            Me.Invoke(act, e)
        Else
            HandleProgressChanged(e)
        End If

    End Sub

    Private Sub HandleProgressChanged(e As System.ComponentModel.ProgressChangedEventArgs)

        Dim progress As WorkProgress = DirectCast(e.UserState, WorkProgress)

        lblTime.Text = progress.TimeText
        lblStatus.Text = progress.Status

    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

    End Sub

    Public Class WorkProgress

        Public TimeText As String
        Public Status As String

        Public Sub New(sTimeText As String, sStatus As String)
            TimeText = sTimeText
            Status = sStatus
        End Sub

    End Class

End Class