开发者

How to work around Cross-thread operation

I am creating a CHAT interface for my game (when networking, server/client style) and I ran into a little problem...

The way it works... I have forms for the SERVER (frmServer) and CLIENTS (frmClient) each of them have a LISTBOX (lbChat) in which I input (lbChat.Items.Add(string)) text as the users type it - in essence a chatbox...

So, let's use the CLIENT as an example (as it is simpler and the concept the same in both client and server cases)... The Client form (frmClient) creates a thread that is used to listen for chat messages (via TCP) - so what I did was pass the listbox itself (lbChat) to the thread thus (I thought) solving my problem of writing into the listbox when chat messages arrive (and are caught by the thread and not frmClient of course)... Now while debugging the code I get the following exception when my thread attempts to write in the listbox (lbChat) of frmClient General Exception: System.InvalidOperationException: Cross-thread operation not valid: Control 'lbChat' accessed from a thread other than the thread it was created on.

So now the question is how do I work around this cross-thread exception? How do I pass information (chat text) from my listener threads (and there will be multiple of them in the field, one per client) to the centralized listbox (lbChat) on the form? I need some kind of method to transfer information while also reducing the chances of running into contention issues (do I need to use ReaderWriterLock?), thing is I have no clue how to accomplish this task (I thought simply passing in the listbox would allow me to write to it in each of the threads)...

Any ideas, hints, and help would be greatly appreciated, thanks this is code for client

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
      开发者_StackOverflow社区  Try
            frmObject.AxWindowsMediaPlayer1.Ctlcontrols.stop()
            reader.Close()
            client.Close()
        Catch exx As Exception
        End Try
    Catch inputoutputException As IOException
    End Try
End Sub

End Class


Call Me.BeginInvoke( ... ) passing a delegate that points to the function that should be called on the UI thread.

E.g.:

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

BeginInvoke and Invoke pass a delegate to be invoked to the UI thread.

EDIT

In the runClient method you access the listbox, playlist and the form itself. This method is running on an other thread than the form was created on so all these calls must be switched to the UI thread using BeginInvoke or Invoke

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜