背景线程与动态对象 [英] background threading with dynamic objects

查看:48
本文介绍了背景线程与动态对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解线程,但我找不到关于它是如何工作的简单答案。



我一直在看例子,但我无法将这些示例调整到我需要的内容,所有内容都与主窗体上已有的对象有关。但是,我的不是,它们是在事件中创造的。我不明白为什么它会对表格做任何说法,因为我正在尝试尝试以任何方式使用它,所以我只是将所有内容都放在主表单上而不是将它分成类。



是否有人能够解释在拉门术语中使用线程时会发生什么...



我有一个后台工作线程,我有一个委托声明,(我认为)它需要保存数据传递给主线程(表单线程)



在子TCP内,我有一个变量= show,它链接到updateform()委托。 updateform()包含由发送者传递的数据字符串。


$ t $ b在子tcp结束时 - 显示=地址txtbox创建,然后运行所有代码。



我应该把代码放在哪里,将对象tb加载到form1.flowlayoutpanel上?是否应该在代表创建中有更多内容?



I'm trying to understand threading, but I can't find a simple answer as to how it works.

I've been looking at examples, but I am having trouble adapting those examples to what I need, everything relates to objects that are already on the main form. But, mine are not, they are created on event. I don't understand why it is saying anything about forms, as I am experimenting to try and get this to work in any way, so I just have everything sitting on the main form rather than separating it into classes.

Is anyone able to explain what happens when using threading in lamens terms...

I've got a background working thread, I've got a delegate declared, (I think) it needs to hold the data to be passed to the main thread (Form thread)

Within sub TCP, I have a variable = show which is linked to the updateform() delegate. updateform() holds datastring which is passed by the sender.

at the end of the sub tcp - show = addressof txtboxcreate which then runs through all that code.

Where am I supposed to put the code to have the object tb, loaded onto form1.flowlayoutpanel? Is there supposed to be something more in the delegate creation?

<pre>Imports System
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports Microsoft.VisualBasic
Imports System.Threading.Thread
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Threading

Public Class main
    Private tcpthread As System.Threading.Thread
    Public Shared datastring As String
    Public Shared counttotal As Integer
    Private Sub main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim tcpthread As New System.Threading.Thread(AddressOf tcp)
        tcpthread.IsBackground = True
        tcpthread.Start()
    End Sub
    Private Delegate Sub updateform(ByVal datastring)
    Private Sub updatefrmtb(ByVal tb As TextBox)
        Me.FlowLayoutPanel1.Controls.Add(tb)
    End Sub
    Private Sub tcp()
        Dim show As updateform
        Dim lf As Decimal = 23
        Dim server As TcpListener
        Dim datastring As String = Nothing
        server = Nothing
        Try
            ' Set the TcpListener on port 13000. 
            'Dim port As Int32 = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Iain-KVS", "p1", Nothing)
            '  Dim ipstring As String = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Iain-KVS", "IP", Nothing)
            Dim port As Int32 = 13000
            Dim localaddr As IPAddress = IPAddress.Parse("127.0.0.1")
            server = New TcpListener(localaddr, port)

            ' Start listening for client requests.
            server.Start()
            '       server.AcceptSocket()

            ' Buffer for reading data 
            Dim bytes(1024) As Byte
            Dim data As String = Nothing

            ' Enter the listening loop. 
            'While True
            '         MsgBox("Waiting for a connection... ")

            ' Perform a blocking call to accept requests. 
            ' You could also user server.AcceptSocket() here.


            Dim client As TcpClient = server.AcceptTcpClient()


            ' Get a stream object for reading and writing 
            Dim stream As NetworkStream = client.GetStream()

            Dim i As Int32
            ' Loop to receive all the data sent by the client.
            i = stream.Read(bytes, 0, bytes.Length)
            'While (i &lt;&gt; 0)
            ' Translate data bytes to a ASCII string.
            data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
            'MsgBox(data)

            ' Process the data sent by the client.
            'data = data.ToUpper()
            Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)


            ' Send back a response.
            stream.Write(msg, 0, msg.Length)
            '         MsgBox("Sent: {0}", data)

            '              i = stream.Read(bytes, 0, bytes.Length)
            datastring = (data)


            ' End While

            ' Shutdown and end connection
            client.Close()
            'End While
        Catch e As SocketException
            Console.WriteLine("SocketException: {0}", e)
        Finally
            server.Stop()
        End Try
        show = AddressOf txtboxcreate

    End Sub 'Main
    Private Sub txtboxcreate(ByVal sender As System.Object)
        Dim count As Integer = 1
        Dim tb As New TextBox
        Name = ("TxtBox" &amp; CStr(counttotal))
        Dim text As String = datastring
        With tb
            .Name = Name
            .Text = Text
            .Multiline = True
            .Height = 150
            .Width = 250
            .ReadOnly = True
            .ScrollBars = False
            .MaxLength = 100
            .Tag = 20
            .BackColor = Color.Black
            .ForeColor = Color.White
            '           move unused properties under here'
            '           tb.ScrollBars = ScrollBars.Both
            '           tb.MaxLength = 100
            '           tb.Height = 100
            '           tb.AutoSize = True
            ' add events to the textbox created


            '       AddHandler tb.MouseClick, AddressOf Me.TextBox1_MouseClick
            '   Form1.textboxestime.Add(tb, 0)
        End With
        count = (count + counttotal)
        ' this defines where the textboxes appear
        updatefrmtb(tb)
    End Sub
End Class</pre><pre></pre>

推荐答案

你的困难很自然。涉及线程之间交换的问题并不像它们看起来那么简单。它们包括具有同步问题的可访问性夫妇的问题。某些方面,即线程启动的事件,在MSDN文档中没有充分解释。



要从线程读取/写入数据,我建议使用线程包装器。在我过去的答案中解释了许多关于线程和线程之间数据交换概念的问题:

如何将ref参数传递给线程 [ ^ ],

在线程(生产者)启动后更改线程(生产者)的参数 [ ^ ],

C#中的MultiThreading [ ^ ]。



这是一些VB.NET示例:将参数传递给线程化的LongRunningProcess [ ^ ]。



另一个方面是从一个线程发送一些更新UI。



您无法从非UI线程调用与UI相关的任何内容。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke() [ ^ ],

使用Treeview扫描仪和MD5的问题 [ ^ ]。



另请参阅有关线程的更多参考资料:

如何让keydown事件在不同的操作上运行vb.net中的线程 [ ^ ],

在启用禁用+多线程后控制事件未触发 [ ^ ]。



-SA
Your difficulties are quite natural. The problems involving exchange between threads are not as trivial as they may seem. They include the problems of accessibility couples with problems of synchronization. Some aspects, event the thread start, are not adequately explained in MSDN documentation.

To read/write data from/to you thread, I suggested using a thread wrapper. Many thins about threading and the concept of data exchange between threads are explained in my past answers:
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^].

This is some VB.NET sample: Passing arguments to a threaded LongRunningProcess[^].

Another aspect is sending some updates from a thread to UI.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA


我现在明白这里发生了什么。但我知道我以后会碰到一些有趣的线程。



你需要打电话给你想要添加的内容。这就是Invoke的作用。



我需要做的就是



I kinda of understand what is going on here now. But I know I'm going to run into some funny threading stuff later on.

You need to call what you want to add. That's what the Invoke thing does.

All I needed to do was

Private Sub updatefrm(ByVal sender As TextBox)
        'The tcp sub runs as a seperate thread. If you try to call the form directly it won't work as you are cross threading
        'you need to invoke "Call" the control you want to do the work with - in this case flowlayoutpanel1
        If InvokeRequired Then
            Invoke(Sub() FlowLayoutPanel1.Controls.Add(sender))
        Else
            FlowLayoutPanel1.Controls.Add(sender)
        End If
    End Sub





通过这样做,我正在检查flowlayoutpanel是否是后台线程的一部分。如果不是,我然后调用(调用)该控件到当前工作线程。现在我可以添加东西了:)



最初我只有flowlayoutpanel1.control.add(发送者)但是因为我没有打电话给面板把它放在上面它提出了交叉线程问题。



简单的3行代码。有时让我疯狂。



By doing this, I'm checking to see if the flowlayoutpanel is part of the background thread. If it's not, I then call (invoke) that control to the current worker thread. Now I can add stuff to it :)

Originally I just had flowlayoutpanel1.control.add(sender) But as I hadn't called the panel to put it on, it comes up with cross threading issues.

3 simple lines of code. Drives me nuts sometimes.


这篇关于背景线程与动态对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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