带线程和类调用的异常 [英] Exception w/ Threading and Invoke in a Class

查看:113
本文介绍了带线程和类调用的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经用尽了时间,精力,精力和精力寻找解决方案,以寻求解决方案.现在,几天后我会寻求帮助:).

我已经为Socket读取创建了一个类,因此我可以在命令中创建套接字.由于执行了套接字读取,由于处于单个线程上,该程序将冻结等待传入的数据.因此,我创建了一个单独的线程来读取袜子,并尝试调用一个事件以防止出现多线程错误.

但是尝试调用时出现错误:在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke."

如何解决此问题,或者有更好的方法来读取袜子而不冻结线程?


插座类:

I have exhausted my time, strength, energy, and searches to find a solution to what I am attempting to do. Now I ask for help days later :).

I have created a class for Socket reads so I can create sockets on command. Due to performing a socket read, the program will freeze waiting for incoming data due to being on a single thread. So I created a separate thread for the reading of the sock and attempt to invoke an event to prevent multi-threading errors.

But I am getting an error when trying to Invoke: "Invoke or BeginInvoke cannot be called on a control until the window handle has been created."

How can I fix this or is there a better way to read a sock without freezing the thread?


Class for Sockets:

Option Explicit On
Option Strict On

Imports System.Text
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

Public Class clsSock
    Inherits Control

    Private Sock As Socket
    Private sName As String, sHost As String, sPort As Integer, sConnected As Boolean

    Public Event Connected(ByVal sockname As String)
    Public Event Read(ByVal sockname As String, ByVal sockread As String)

    Delegate Sub onRead(ByVal msg As String)
    Private _onRead As onRead

    Dim tdReadSock As Thread

    Public Sub New()
        _onRead = New onRead(AddressOf RaiseRead)
    End Sub

    Public Sub Open(ByVal name As String, ByVal host As String, ByVal port As Integer)
        'define endpoint, connect socket
        Dim ipHost As IPHostEntry = Dns.GetHostEntry(host)
        Dim ipEnd As New IPEndPoint(ipHost.AddressList(0), port)
        Sock = New Socket(ipEnd.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
        Sock.Connect(ipEnd)

        'assign local variables
        sName = name
        sHost = host
        sPort = port
        sConnected = True

        'raise an event for connection success
        RaiseEvent Connected(name)

        'start new thread for socket reading to prevent application freezing from STA
        tdReadSock = New Thread(New ThreadStart(AddressOf sockMonitor))
        tdReadSock.Start()
    End Sub

    Public Sub Send(ByVal sockdata As String)
        Dim data() As Byte = ASCIIEncoding.UTF8.GetBytes(sockdata & vbCrLf)
        Sock.Send(data, data.Length, SocketFlags.None)
    End Sub

    Private Sub sockMonitor()
        'loop while sock is connected, wait for receive, raise event for read
        Do While Sock.Connected = True
            Dim data(4096) As Byte

            Sock.Receive(data)
            Dim msg As String, msgs() As String = ASCIIEncoding.UTF8.GetString(data).Trim(Chr(0)).Split(CChar(vbCrLf))

            For Each msg In msgs
                If msg.Length > 0 Then BeginInvoke(_onRead, New Object() {msg})
            Next
        Loop
    End Sub

    Private Sub RaiseRead(ByVal msg As String)
        RaiseEvent Read(sName, msg)
    End Sub
End Class




调用代码:




Code for calling:

Private WithEvents Socks As clsSock

Private Sub Sock_Connected(ByVal state As String) Handles Socks.Connected
    MsgBox("Connected - " & state)
    Socks.Send("/GET etc etc etc")
End Sub
Private Sub Sock_Read(ByVal sockname As String, ByVal sockread As String) Handles Socks.Read
    Text1.AppendText(sockname & " - " & sockread & vbCrLf)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Socks = New clsSock()
    Socks.Open("google", "google.com", 80)
End Sub



任何帮助都将非常有用.



Any help would be great.

推荐答案

您的控件必须是控件,它是使用调用的UI的一部分.您需要将其插入到其他控件中,该控件已经是您的表单和UI的一部分.

您似乎不了解Invoke/BeginInvoke的用法.这不是防止多线程错误"(您是什么意思的神秘错误?!),而是在UI线程上使用UI调用某些委托.委托和调用参数被放入队列; UI线程使用此队列进行实际调用.

有关更多详细信息,请参见我对先前的一些问题的解答:
Control.Invoke()与Control.BeginInvoke() [ ^ ]
Treeview Scanner和MD5的问题 [来自同一端口号的多个客户端 [ http://en.wikipedia.org/wiki/Loose_coupling [ ^ ]),并且将UI与功能完全隔离.您需要一个或两个线程(取决于客户端或服务器端,请参见上面的参考资料,关于网络的答案)进行网络连接,并从一个线程调用UI方法.

—SA
You control has to be a control, a part of your UI to use invocation. You need to insert is into some other control which is already a part of your form and UI.

You don''t seem to understand the use of Invoke/BeginInvoke. This is not "to prevent multi-threading errors" (what mysterious errors did you mean?!) but to call some delegates using UI on UI thread. The delegates and call parameters are put to queue; and this queue is used by the UI thread for actual calls.

See my Answers to some previous Questions for more detail:
Control.Invoke() vs. Control.BeginInvoke()[^]
Problem with Treeview Scanner And MD5[^]
Multple clients from same port Number[^]

From these reference, you will find my design sketched on typical use of threading. If you understand this, you should doubt about a way you''re trying to use you control. You should re-design it. Why doing socket operation in control? You should couple UI with you thread loosely (http://en.wikipedia.org/wiki/Loose_coupling[^]) and isolate UI from functionality very thoroughly. You need to have one or two threads (depending on client or server side, see my references above, the Answers about networking) for your networking and invoke UI methods from a thread.

—SA


这篇关于带线程和类调用的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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