0
Hy there!从后台工作线程和基类更新GUI控制
首先。我已经阅读了很多其他相关的问题,但没有回答我的问题(一个或多个)
我有一个WinForm应用程序,这使得在某些设备上的一些测试,还记录了进展。我们来举个例子。
UI是主要的形式。
从UI我开始一个后台工作。在里面我做测试。
A是基类。 B继承了A并添加了更多方法。
我的目的是从日志消息:
- 在MainForm的UI
- 从后台工作的DoWork方法
- 从B类
- 从A类
我能做到这一点,除了对于最后一种情况。看来,另一个富文本框被创建,其中有文本,但从不显示...
我已经创建了一个名为“记录器”,它具有一些功能,将登录到一个文件,显示一个对话框和模块登录到一个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
因此,请求是:
我想更新我的rtbMessageLog.Text从A类(或基类 - 见示例代码)
谢谢
这是一个很大的消化,但也许你应该如何显示消息的记录器模块分开。例如也许你最初的'公共子日志(消息作为字符串,可选的messageType作为消息类型= MessageType.ErrorMessage)'可能引发一个事件,你可以在MainForm类中处理更新RTB或显示一个消息框(使用InvokeRequired等获得在UI线程上),并且你可以在其他地方处理它以登录到一个文件等等。只是在此刻抛出一些想法! – Mark
同意。你的A类和B类应该提出一个表单订阅的**事件**。当收到时,我会使用Invoke()或SynchronizationContext方法来更新UI ... **但是**您会使用Form/Control的直接引用,因为您已经在那里了(因为这是事件发生的位置被接收)。你根本不需要任何Shared成员。 –
谢谢您的想法......我会尽量在几个小时内实施它们......从未想过要使用活动...... –