将文本框更新为与backgroundworker不同的形式 [英] Update textbox to a different form from backgroundworker

查看:125
本文介绍了将文本框更新为与backgroundworker不同的形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两种形式,即Form1和Newform. Form1有两个按钮和一个文本框,Newform有其自己的文本框.我正在使用settext子集来调用backgroundworker中的委托子集来更新两种形式的文本框.

I have two forms, Form1 and Newform. Form1 has two buttons and a textbox and Newform has its own textbox. I am using a settext sub to invoke a delegate sub in the backgroundworker to update the textbox in both forms.

Form1中的文本框似乎正在更新,但是Newform中的文本框没有更新.

The textbox in Form1 seems to be updating but the textbox in Newform isn't updating.

如果我想以其他形式更新文本框,是否缺少某些内容?

Is there something that I'm missing if I want to update the textbox on a different form?

先谢谢了.

Imports System.Threading
Public Class Form1
Dim stopbit As Boolean
Dim TestingComplete As Boolean
Dim ReadValue As Double
Dim FinalValue As Double

Delegate Sub SetTextCallback(ByRef Txtbox As TextBox, ByVal Txt As String)

'Thread Safe textbox update routine
Private Sub SetText(ByRef Txtbox As TextBox, ByVal Txt As String)

    ' InvokeRequired required compares the thread ID of the
    ' calling thread to the thread ID of the creating thread.
    ' If these threads are different, it returns true.
    Console.WriteLine(Txtbox.InvokeRequired & "  textbox invokerequired")

    If Txtbox.InvokeRequired Then
        Try
            'MsgBox("inside settext")
            Txtbox.Invoke(New SetTextCallback(AddressOf SetText), Txtbox, Txt)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    Else
        Txtbox.Text = Txt
        Txtbox.Update()
    End If
End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    newform.Show()
End Sub

Function ReadTemp() As Double
    ReadValue = ReadValue / 2
    Return ReadValue
End Function

Sub Test()
    Dim starttime As Integer
    Dim EllapsedTime As Integer
    Dim OldValue As Double = 0
    Dim NewValue As Double = 0
    Dim Difference As Double = 1
    Dim Margin As Double = 0.1

    stopbit = False
    starttime = My.Computer.Clock.TickCount
    Do
        Thread.Sleep(200)
        OldValue = NewValue
        NewValue = ReadTemp()
        Difference = Math.Abs(NewValue - OldValue)
        SetText(Me.TextBox1, Difference.ToString)
        SetText(newform.TextBox1, Difference.ToString)
        newform.Refresh()
        EllapsedTime = My.Computer.Clock.TickCount - starttime


    Loop Until EllapsedTime > 5000 Or stopbit = True ' Or Difference < Margin
    FinalValue = NewValue
    TestingComplete = True

End Sub

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

    BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    stopbit = True
End Sub

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

    For i As Integer = 1 To 10
        ReadValue = 100000
        TestingComplete = False
        ThreadPool.QueueUserWorkItem(AddressOf Test)

        Do
            Thread.Sleep(200)
        Loop Until TestingComplete = True
        MsgBox("Final Value  " & FinalValue)
    Next

End Sub

结束班级

推荐答案

您的问题是由于您使用的是默认实例.在VB.NET中,默认表单实例是一项功能,使您可以通过其类型名称访问表单,而不必手动创建它的实例.

Your issue is due to that you're using the default instance of newform. In VB.NET default form instances is a feature that allows you to access a form via its type name without having to manually create an instance of it.

换句话说,它允许您执行以下操作:

In other words it lets you do this:

newform.Show()
newform.TextBox1.Text = "Something"

...不是正确的方法,而是这样:

...instead of doing it the correct way, which is this:

Dim myNewForm As New newform
myNewForm.Show()
myNewForm.TextBox1.Text = "Something"

上面,我们创建了名为myNewFormnewform的新实例.为了能够使用框架中的 most 个对象(包括表单),这是必需的.但是,VB.NET通过提供为您创建实例来简化此行为,这就是我的第一个示例.

Above we create a new instance of newform called myNewForm. This is required to be able to use most objects in the framework (including forms). However, VB.NET simplifies this behaviour by offering to create the instance for you, which is what is going on in my first example.

这些默认实例的问题在于它们是特定于线程的,这意味着将为使用此行为的每个线程创建一个新实例.

The problem with these default instances is that they are thread-specific, meaning a new instance is created for every thread that you use this behaviour in.

因此您在执行操作时所引用的表单:

Thus the form you refer to when you do:

newform.Show()

...与您在线程中引用的形式不同,因为在该线程中为它创建了一个新实例:

...is not the same form that you refer to in your thread, because a new instance has been created for it in that thread:

'This is not the same "newform" as above!
SetText(newform.TextBox1, Difference.ToString)

解决方案当然是自己创建实例,从而使您可以完全控制正在发生的事情:

The solution to this is of course to create the instance yourself, allowing you to have full control over what's going on:

Dim newFrm As New newform

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    newFrm.Show()
End Sub

...your code...

Sub Test()
    ...your code...

    SetText(newFrm.TextBox1, Difference.ToString)

    ...even more of your code...
End Sub


作为旁注,您可以删除对newform.Refresh()Txtbox.Update()的呼叫.这些只是通过迫使表单和文本框重新绘制自身而导致不必要的开销,当您更改影响其内容/设计的任何属性时,此操作已经完成(因此,实际上是使它们重新绘制两次).


As a side note you can remove your calls to newform.Refresh() and Txtbox.Update(). These just cause unnecessary overhead by forcing the form and text boxes to redraw themselves, which is already done when you change any of their properties that affect their contents/design (so you are essentially making them redraw themselves twice).

此外,如果您要调用UI线程更简单,并且使用的是Visual Studio/Visual Basic 2010 或更高版本 ,您可以切换到使用 lambda表达式 ,而不是常规委托.它们更易于使用,并允许您在线创建可在UI线程上调用的整个方法.

Also, if you want to make invoking to the UI thread simpler and you are using Visual Studio/Visual Basic 2010 or newer, you could switch to using lambda expressions instead of regular delegates. They're much easier to use and allows you to create whole methods in-line that can be invoked on the UI thread.

为此,我编写了一个名为InvokeIfRequired()的扩展方法,该方法可让您在UI线程上调用 any 方法/函数,并为您检查InvokeRequired.它与您现在拥有的类似,仅适用于任何控件(不仅限于文本框),并具有lambda表达式,可让您在UI上运行所需的任何代码.

For this purpose I've written an extension method called InvokeIfRequired() which lets you invoke any method/function on the UI thread, checking InvokeRequired for you. It's similar to what you have now, only it works for any control (not just text boxes) and with lambda expressions, allows you to run any code you want on the UI.

您可以通过将模块添加到项目(Add New Item... > Module)并将其命名为Extensions来使用它.然后将以下代码放入其中:

You can use it by adding a module to your project (Add New Item... > Module) and naming it Extensions. Then put this code inside it:

Imports System.Runtime.CompilerServices

Public Module Extensions
    ''' <summary>
    ''' Invokes the specified method on the calling control's thread (if necessary, otherwise on the current thread).
    ''' </summary>
    ''' <param name="Control">The control which's thread to invoke the method at.</param>
    ''' <param name="Method">The method to invoke.</param>
    ''' <param name="Parameters">The parameters to pass to the method (optional).</param>
    ''' <remarks></remarks>
    <Extension()> _
    Public Function InvokeIfRequired(ByVal Control As Control, ByVal Method As [Delegate], ByVal ParamArray Parameters As Object()) As Object
        If Parameters IsNot Nothing AndAlso _
            Parameters.Length = 0 Then Parameters = Nothing

        If Control.InvokeRequired = True Then
            Return Control.Invoke(Method, Parameters)
        Else
            Return Method.DynamicInvoke(Parameters)
        End If
    End Function
End Module

这允许您通过执行以下操作来调用任一行代码:

This allows you to invoke either one line of code by doing:

Me.InvokeIfRequired(Sub() Me.TextBox1.Text = Difference.ToString())

或者通过执行以下操作来调用整个代码块:

Or to invoke a whole block of code by doing:

Me.InvokeIfRequired(Sub()
                        Me.TextBox1.Text = Difference.ToString()
                        newFrm.TextBox1.Text = Difference.ToString()
                        Me.BackColor = Color.Red 'Just an example of what you can do.
                    End Sub)

这篇关于将文本框更新为与backgroundworker不同的形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆