2011-05-14 6 views
1

내 게임 (네트워킹, 서버/클라이언트 스타일)에 대한 채팅 인터페이스를 만들고 있는데 약간의 문제가 발생했습니다 ...크로스 스레드 작업을 해결하는 방법

작동 방식 ... SERVER (frmServer) 및 CLIENT (frmClient)에 대한 양식이 있습니다. 각 양식에 사용자가 입력 할 때 lbChat.Items.Add (string)) 텍스트를 입력하는 LISTBOX (lbChat)가 있습니다.

그래서 클라이언트와 서버의 경우 모두 간단하고 개념이 동일하므로 예제를 사용하십시오 ... 클라이언트 양식 (frmClient)은 수신 대기하는 스레드를 만듭니다 채팅 메시지 (TCP를 통해) - 그래서 내가 한 일은 목록 상자 자체를 통과 (lbChat) 그래서 스레드 메시지 (및 frmClient 물론 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 

최종 클래스

+0

중복 가능한 [크로스 스레드 연산이 유효하지 않습니다] (http : // stackoverflow. com/questions/5624033/cross-thread-operation-not-valid) –

답변

2

Me.BeginInvoke(...)을 호출하면 해당 함수를 가리키는 대리자가 전달됩니다. UI 스레드에서 호출되어야합니다.

예컨대 :

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

BeginInvoke 및 호출 대리자 전달은 UI 스레드에 호출된다.

당신이 목록 상자, 재생 목록 및 양식 자체에 액세스 runClient 방법에서 편집

. 이 메서드는 폼이 작성된 것보다 다른 스레드에서 실행되므로 BeginInvoke 또는 Invoke를 사용하여 이러한 모든 호출을 UI 스레드로 전환해야합니다.

+0

시도해 보았지만 작동하지 않았다. – kelly

+0

그냥 추가하면 폼 내에서'Me.InvokeRequired'를 검사하여 _not_인지 확인한다. UI 스레드에서 ('True'). 그렇지 않다면, UI 스레드에 자신을두기 위해 호출을 '호출'해야합니다. 그렇다면 처리 할 수 ​​있습니다. – pickypg

+0

'만약 (frmMain.ListBox1.InvokeRequired()) 다음 frmMain.ListBox1.Invoke (새로운 AF (AddressOf를 재미)) frmMain.ListBox1.Items.Add (항목) 그렇지 frmMain.ListBox1.Items.Add (항목) 끝 '만약 당신이 무슨 말을하고 있지만 그것 do'nt 작품 – kelly

관련 문제