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成員。 –
謝謝您的想法......我會盡量在幾個小時內實施它們......從未想過要使用活動...... –