从后台工作线程和基类更新GUI控件

时间:2017-06-28 15:42:22

标签: vb.net thread-safety controls

Hy那里!

首先。我已经阅读了很多其他相关问题但没有回答我的问题

我有一个Winform应用程序,可以对某些设备进行一些测试,并记录进度。让我们举个例子。

用户界面是主要形式。

来自UI的

我开始一个后台工作者。在里面我做了测试。

A是基类。 B继承A并添加更多方法。

我的目的是记录来自的信息:
- 主形式UI
- 来自后台工作者的DoWork方法
- 来自B班
- 来自A班

除了最后一种情况,我可以做到这一点。似乎创建了另一个富文本框,其中包含文本但从未显示...

我创建了一个名为" Logger"的模块,它有一些函数可以登录到文件,显示对话框并登​​录到richtextbox(或控件)

理解和尝试的示例代码:

Public Shared frm As MainForm
Public Shared bgW As BackgroundWorker
Public Shared syncContext As SynchronizationContext

Public Sub New() ' construtor of the main form
' This call is required by the designer.
InitializeComponent()
frm = Me
bgW = bgWorker
syncContext = SynchronizationContext.Current
End Sub

Public Module Logger

''' Logs messages into a log file. Each day a new log file is made.
Public Sub Log(message As String, Optional messageType As MessageType = MessageType.ErrorMessage)

Try
Catch ex As Exception
End Try

End Sub

' here goes the method the logs into the control. Examples in the ''approaches'' section

End Module


Public Class A

Public Sub LogA()
Logger.Log("someting")
End Sub

End Class

Public CLass B
Inherits A

Public Sub LogB()
Logger.Log("nothing")
End Sub

Public Sub Do()
MyBase.LogA()
End Sub

End Class

Public Class Test
public Sub Run()

Dim bObj as new B()
bObj.LogB()
bObj.Do()

End Sub

End Class


Private Sub BtnReset_Click(sender As Object, e As EventArgs) Handles btnReset.Click
Logger.Log("inside click")
bgWorker.RunWorkerAsync()
End Sub

Private Sub BgWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Logger.Log("inside do work")

Dim t as new Test()
t.Run()

End Sub

方法1

使用线程安全

 Dim tempForm As Form
Public Sub Log(destinationControl As RichTextBox, mainForm As Form, message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)
        ' cross operation exception
        If Not String.IsNullOrWhiteSpace(message) Then
            tempForm = mainForm
            LogInRichTextBox(destinationControl, message, messageType, textColor, textFont)
        End If

End Sub

  Private Sub LogInRichTextBox(destinationControl As RichTextBox, message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)

    If destinationControl.InvokeRequired Then
        Dim myDelegate As New LogInBoxDelegate(AddressOf LogInRichTextBox)
        tempForm.Invoke(myDelegate, New Object() {destinationControl, message, messageType, textColor, textFont})
    Else
        destinationControl.AppendText(vbCrLf)
    End If

End Sub

方法2

使用共享变量

  Public Sub Log( mainForm As Form, message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)
        ' cross operation exception
        If Not String.IsNullOrWhiteSpace(message) Then
            tempForm = mainForm
            LogInRichTextBox(message, messageType, textColor, textFont)
        End If

End Sub

  Private Sub LogInRichTextBox(message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)

    If  MainForm.frm.rtbMessageLog.InvokeRequired Then
        Dim myDelegate As New LogInBoxDelegate(AddressOf LogInRichTextBox)
        tempForm.Invoke(myDelegate, New Object() { MainForm.frm.rtbMessageLog, message, messageType, textColor, textFont})
    Else
        MainForm.frm.rtbMessageLog.AppendText(vbCrLf)
    End If

End Sub

方法3
使用后台工作人员报告进度'

 Public Sub Log( mainForm As Form, message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)
        ' cross operation exception
        If Not String.IsNullOrWhiteSpace(message) Then
            tempForm = mainForm
            LogInRichTextBox(message, messageType, textColor, textFont)
        End If

End Sub

  Private Sub LogInRichTextBox(message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)

    MainForm.bgW.ReportProgress(0,message)

End Sub

     Private Sub BgWorker_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgWorker.ProgressChanged

               rtbMessageLog.AppendText(CStr(e.UserState))

    End Sub

方法4
使用同步上下文

Public Sub Log( mainForm As Form, message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)
        ' cross operation exception
        If Not String.IsNullOrWhiteSpace(message) Then
            tempForm = mainForm
            LogInRichTextBox(message, messageType, textColor, textFont)
        End If

End Sub

  Private Sub LogInRichTextBox(message As String, messageType As MessageType, Optional textColor As Color = Nothing, Optional textFont As Font = Nothing)

    MainForm.syncContext.Post(New Threading.SendOrPostCallback(Sub() MainForm.rtbMessageLog.AppendText(message)), Nothing)

End Sub

所以,请求是:

我想从A类(或基类 - 参见示例代码)更新我的rtbMessageLog.Text

谢谢

1 个答案:

答案 0 :(得分:1)

借助@Mark和@Idle_Mind的评论,我成功找到了解决方案。非常感谢你

我发布了一些代码,也许会帮助别人:

Public Module Logger

    Public Event LogInRichTextBoxEvent(message As String, textColor As Color, textFont As Font)
    Delegate Sub LogInBoxDelegate(message As String, textColor As Color, textFont As Font)

    ''' Logs messages into a log file. Each day a new log file is made.
    Public Sub Log(message As String, Optional messageType As MessageType = MessageType.ErrorMessage)
        Try
         RaiseEvent LogInRichTextBoxEvent(message, textColor, textFont)
        Catch ex As Exception
        End Try
    End Sub

    ' here goes the method the logs into the control. Examples in the ''approaches'' section

End Module

Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Try
        AddHandler Logger.LogInRichTextBoxEvent, AddressOf ShouldLoggerHandler
    catch ex as exception
    End try
End Sub

Private Sub ShouldLoggerHandler(message As String, textColor As Color, textFont As Font)
    If rtbMessageLog.InvokeRequired Then
        Dim myDelegate As New LogInBoxDelegate(AddressOf ShouldLoggerHandler)
        Me.Invoke(myDelegate, New Object() {message, textColor, textFont})
    Else
        rtbMessageLog.AppendTxet(message)
    End if
End Sub