从主要UI中提升事件 [英] Raise event in Main UI from tread

查看:58
本文介绍了从主要UI中提升事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hej



我在编程方面已经退出了新的但是喜欢在业余爱好规模上做,我的问题是如何在主线程中从其他人那里引发一个事件线程?

从线程我想使用Sub WriteEvent,我想在主窗体上触发一个事件,我得到错误交叉线程。

< br $>
以下代码



提前致谢



Hej

I am quit new in programming but enjoy doing it on a hobby scale, my question is how to raise an event in the main thread from an other thread?
From the thread i want to use Sub WriteEvent, witch i would like to trigger a event, on the main form, i get the error cross threading.

Code below

Thanks in advance

Imports System.IO
Imports System.Net
Imports System.Threading

Public Class frmMain
    Private _tdatabase As Thread

    Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        AddHandler EventlogChange, AddressOf Eventlog_changed

        _tdatabase = New Thread(AddressOf Me.Database)

        _tdatabase.IsBackground = True
        _tdatabase.Start()
        _tdatabase.Join()
    End Sub

    Private Sub Eventlog_changed(ByVal sender As Object, ByVal e As EventLogArgs)
        TextBox1.Text = e.GetEntries
    End Sub

    Private Sub Database()
        WriteEntry("Test")
    End Sub

#Region "EventLog"
    Private Event EventlogChange As EventHandler(Of EventLogArgs)

    Sub WriteEntry(ByVal description As String)
        If (InvokeRequired) Then

        Else
            'Declare objects.
            Dim _stream As StreamWriter

            'Execute code in try statement.
            Try
                'Create new instance of streamwriter.
                _stream = New StreamWriter(My.Computer.FileSystem.CurrentDirectory.ToString & "\Event.log", True)

                'Write data to streamer.
                _stream.WriteLine(String.Format("{0},{1};", DateTime.Now.ToString("dd'-'MM'-'yyyy' 'hh':'mm':'ss':'fff"), description.ToString))

                'Flush streamer, clear stream buffer.
                _stream.Flush()

                'Close streamer, release all resources.
                _stream.Close()
            Catch ex As Exception
                'On exception, below code will be executed.

                'Throw exception.
                Throw ex

                'Notify user.
                MsgBox("Unable to read eventlog.", MsgBoxStyle.Exclamation, "Eventlog")
            Finally
                'When try finished, below code will be executed.

                'Raise eventlog change event.
                RaiseEvent EventlogChange(New String() {"Eventlog"}, New EventLogArgs)
            End Try
        End If
    End Sub

    Public Class EventLogArgs
        Inherits System.EventArgs

        Public Function GetEntries() As String
            'Declare objects.
            Dim _stream As StreamReader
            Dim _data As String

            'Execute code in try statement.
            Try
                'Create new instance of streamreader
                _stream = New StreamReader(My.Computer.FileSystem.CurrentDirectory.ToString & "\Event.log")

                'Fill string object whit data readed from streamer.
                _data = _stream.ReadToEnd()

                'Close streamer, release all resources.
                _stream.Close()

                'Return string object readed from streamer.
                Return _data
            Catch ex As Exception
                'On exception, below code will be executed.

                'Throw exception.
                Throw ex

                'Notify user.
                MsgBox("Unable to read eventlog.", MsgBoxStyle.Exclamation, "Eventlog")

                'Return noting.
                Return Nothing
            End Try
        End Function
    End Class
#End Region
End Class

推荐答案

嗯,要考虑的一件事可能是直接调用来自其他地方的表单代码可能不是这里最好的整体程序结构。你可能会考虑创建一个类来执行事件日志编写并引发自己的事件,然后让表单拥有该类型的对象并订阅它的事件。



但是,尽管可以提供更清晰的关注点分离,但您仍需要解决此处存在的问题。事件调用本身并不会导致麻烦,更新winforms控件(就像在事件处理程序中一样)并不是一个线程安全的操作。只能从创建和拥有控件的线程内安全地更新控件。幸运的是,有一种方法可以让表单的控制线程使用 Invoke 方法来完成调用指定方法本身的工作。



我相信你想要的是在表格的代码中是这样的:

Well, one thing to consider might be that calling directly into your form's code from somewhere else might not be the best overall program structure here. You might think about instead creating a class that does your event log writing and raises its own events, then have the form own an object of that type and subscribe to its events.

However, while that might provide a cleaner separation of concerns, you still would need to solve the problem you have here. It isn't the event call itself that causes the trouble, it is that updating a winforms control (as you do inside the event handler) is not a thread-safe operation. A control can only be updated safely from within the thread that created and owns the control. Luckily, there is a way provided to ask the form's control thread to do the work of calling a specified method itself, using the Invoke method.

I believe what you want is something like this in the form's code:
Delegate Sub textUpdater(newText as String)

Public Sub updateTextBox1(newText As String)
    ' The "InvokeRequired" property is thread-safe for reading.
    ' It returns false whenever we call it from the thread that owns the control,
    ' true when we are in a different thread.
    If Me.TextBox1.InvokeRequired Then
        ' The form has a thread-safe method called "Invoke" which takes a delegate
        ' and basically asks the form's control thread to execute the specified
        ' function instead of executing it directly.
        Me.Invoke(New textUpdater(AddressOf updateTextBox1), newText)
    Else
        TextBox1.Text = newText
    End If
End Sub

Private Sub Eventlog_changed(ByVal sender As Object, ByVal e As EventLogArgs)
    updateTextBox1(e.GetEntries())
End Sub



我们这里得到的是一个方法( updateTextBox1 ),现在可以安全地从任何线程执行。如果从表单自己的控制线程调用它,它只是更新文本框。如果不是,它会使用 Invoke 将自己的地址交给表单的控制线程,这样就会再次调用相同的函数,这次来自正确的线程。


What we've got here is a method (updateTextBox1) which can now safely be executed from any thread. If it is being called from the form's own control thread, it just updates the text box. If it is not, it hands its own address to the form's control thread using Invoke so the same function will be called again, this time from the proper thread.


这篇关于从主要UI中提升事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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