如何解决跨线程操作

时间:2011-05-14 17:56:17

标签: .net vb.net

我正在为我的游戏创建一个CHAT界面(当网络,服务器/客户端风格时),我遇到了一个小问题......

它的工作方式......我有SERVER(frmServer)和CLIENTS(frmClient)的表单,每个表单都有一个LISTBOX(lbChat),我在其中输入(lbChat.Items.Add(string))文本作为用户输入它 - 本质上是一个聊天框......

所以,让我们以CLIENT为例(因为它更简单,在客户端和服务器情况下概念相同)...... 客户端表单(frmClient)创建一个用于侦听聊天消息的线程(通过TCP) - 所以我所做的就是将列表框本身(lbChat)传递给线程,因此(我认为)解决了写入列表框的问题当聊天消息到达时(并且被线程捕获而当然不是frmClient)... 现在在调试代码时,当我的线程尝试在frmClient的列表框(lbChat)中写入时,我得到以下异常 常规异常:System.InvalidOperationException:跨线程操作无效:控制从其创建的线程以外的线程访问的“lbChat”。

所以现在问题是如何解决这个跨线程异常?如何将来自我的侦听器线程的信息(聊天文本)(在该字段中将有多个,每个客户端一个)传递到表单上的集中列表框(lbChat)? 我需要某种方法来传输信息,同时也减少了遇到争用问题的机会(我是否需要使用ReaderWriterLock?),事情是我不知道如何完成这项任务(我想只需传入列表框就可以了我在每个线程中写到它... ...

非常感谢任何想法,提示和帮助,谢谢 这是客户端的代码

Imports System.Net.Sockets
Imports System.Windows.Forms
Imports System.IO
Imports System.Threading

Public Class recieve

Private reader As BinaryReader
Private message As String = ""
Private frmObject As frmMain
Private readthred As Thread
Private Delegate Sub af(ByVal item As String)
Public Sub fun(ByVal item As String)
    If (frmMain.ListBox1.InvokeRequired()) Then
        frmMain.ListBox1.Invoke(New af(AddressOf fun))
        frmMain.ListBox1.Items.Add(item)
    Else
        frmMain.ListBox1.Items.Add(item)

    End If
End Sub
Public Sub New(ByVal frmObject As frmMain)
    MyBase.New()
    Me.frmObject = frmObject
    readthred = New Thread(AddressOf runClinet)
    readthred.SetApartmentState(ApartmentState.STA)
    readthred.Start()

End Sub



Public Sub runClinet()
    Dim client As TcpClient
    Try
        client = New TcpClient()
        client.Connect("127.0.0.1", 5234)
        reader = New BinaryReader(client.GetStream())
        Try
            Dim Path As String
            Path = reader.ReadString
            frmMain.ListBox1.SelectedItem = Path

            frmObject.Playlist.SelectedItem = frmObject.ListBox1.SelectedItem
            frmMain.AxWindowsMediaPlayer1.URL = Path
            frmObject.ListBox1.Items.Add(Path)
            frmObject.Playlist.Items.Add(Path)
            Try
                While True
                    Path = reader.ReadString
                    Select Case Path
                        Case "1"
                            frmObject.AxWindowsMediaPlayer1.Ctlcontrols.pause()
                        Case "2"
                            frmObject.AxWindowsMediaPlayer1.Ctlcontrols.play()
                        Case "3"
                            frmObject.AxWindowsMediaPlayer1.Ctlcontrols.stop()
                    End Select
                End While
            Catch ex As Exception
            End Try
        Catch inputoutputException As IOException
        Finally
        End Try
        Try
            frmObject.AxWindowsMediaPlayer1.Ctlcontrols.stop()
            reader.Close()
            client.Close()
        Catch exx As Exception
        End Try
    Catch inputoutputException As IOException
    End Try
End Sub

结束班

1 个答案:

答案 0 :(得分:2)

调用Me.BeginInvoke( ... )传递一个指向应该在UI线程上调用的函数的委托。

E.g:

Me.BeginInvoke(New MyDelegate(AddressOf DelegateMethod), parameterArray)

BeginInvoke和Invoke传递一个委托来调用UI线程。

修改

在runClient方法中,您可以访问列表框,播放列表和表单本身。此方法在创建表单之外的其他线程上运行,因此必须使用BeginInvoke或Invoke

将所有这些调用切换到UI线程