게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
c# 크로스 쓰래드 때문에 invoke를 썻는데 ..
게시물ID : programmer_17483짧은주소 복사하기
작성자 : 토왕
추천 : 0
조회수 : 1081회
댓글수 : 6개
등록시간 : 2016/06/03 22:13:20
옵션
  • 본인삭제금지
제가  서버를 하려고  하고있는데 크로스 쓰래드 문제가 생겨서   invoke를 
해봤는데  이게  이제 연결은 되는데 문자가 떠야 될 부분들이 안뜨네요 ;;
 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net; // IPAddress
using System.Net.Sockets; //TcpListener 클래스사용
using System.Threading; //스레드 클래스 사용
using System.IO; //파일 클래스 사용

namespace WindowsFormsApplication4
{

    public partial class Form1 : Form
    {
        private TcpListener Server; //TCP 네트워크 클라이언트에서 연결 수신
        private TcpClient SerClient; //TCP 네트워크 서비스에 대한 클라이언트 연결 제공
        private NetworkStream myStream; //네트워크 스트림
        private StreamReader myRead; //스트림 읽기
        private StreamWriter myWrite; //스트림 쓰기
        private Boolean Start = false; //서버 시작
        private Boolean ClientCon = false; //클라이언트 시작
        private int myPort; //포트
        private string myName; //별칭(ID)
        private Thread myReader, myServer; //스레드
        private Boolean TextChange = false; //입력 컨트롤의 데이터입력 체크
        private delegate void AddTextDele(string str);
        private AddTextDele AddText;

        public Form1()
        {
            InitializeComponent();
        }

        private void 설정ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.설정ToolStripMenuItem.Enabled = false;//메뉴비활성화
            this.plOption.Visible = true;//설정을 위한 상자 open
            this.txtId.Focus();//id입력상자로 초점이동

        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            ControlCheck();
        }
        private void ControlCheck()
        {
            if (this.txtId.Text == "")//ID가 입력되지 않았으면 ID입력
            {
                this.txtId.Focus();
            }
            else if (this.txtPort.Text == "")//PORT가 입력되지 않았으면 PORT입력
            {
                this.txtPort.Focus();
            }
            else
            {
                try
                {
                    this.plOption.Visible = false;//설정이 완료되었으므로 설정상자를 비활성화
                    this.설정ToolStripMenuItem.Enabled = true;//상위메뉴바 활성화
                    this.tsbtnConn.Enabled = true;//연결메뉴 활성화
                }
                catch
                {//에러메세지 박스 출력
                    MessageBox.Show("설정이 저장되지 않았습니다.", "에러", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.설정ToolStripMenuItem.Enabled = true; //설정 메뉴 활성화
            this.plOption.Visible = false; //입력창 닫기
            this.txtMessage.Focus();
        }

        private void tsbtnConn_Click(object sender, EventArgs e)
        {
            var addr = new IPAddress(0);//IPAddress 클래스의 개체를 초기화, 매개변수가 0->로컬단말의 아이피 가져옴
            this.myName = this.txtId.Text;
            this.myPort = Convert.ToInt32(this.txtPort.Text);
            if (!(this.Start))//서버가 시작되지 않은 경우 
            {
                try
                {
                    Server = new TcpListener(addr, this.myPort);//ip주소와 포트번호를 인자로 TcpLIstener의 개체 생성
                    Server.Start();//Server 시작

                    this.Start = true;
                    this.txtMessage.Enabled = true;
                    this.btnSend.Enabled = true;
                    this.txtMessage.Focus();//메시지를 쓸 수 있도록 초점을 이동
                    this.tsbtnDisconn.Enabled = true;//연결을 끊을 수 있도록 메뉴 활성화
                    this.tsbtnConn.Enabled = false;//연결시도버튼 비활성화
                                                   //Thread클래스의 생성자를 이용하여 개체생성-> ServerStart()메서드로 클라이언트의 수신과 네트워크 스트림의 값을 수신하는 작업을 새로 생성한 스레스에서 수행 
                    myServer = new Thread(ServerStart);
                    myServer.Start();
                    this.설정ToolStripMenuItem.Enabled = false;
                }
                catch
                {
                    MessageView("서버를 실행할 수 없습니다.");
                }
            }
            else
            {
                ServerStop(); //ServerStop() 함수 호출
            }

        }

        private void MessageView(string strText)
        {
            this.rtbText.AppendText(strText + "\r\n");//입력한 텍스트와 엔터키추가
            this.rtbText.Focus();//초점이동
            this.rtbText.ScrollToCaret();// 컨트롤의 내용을 현재 캐럿 위치까지 스크롤
            this.txtMessage.Focus();//초점이동
        }
        private void ServerStart()
        {  //메세지출력
            rtbText.Invoke(AddText, "서버 실행 : 챗 상대의 접속을 기다립니다...");
            while (Start)//클라이언트가 접속될 때까지 기다림
            {
                try
                {
                    SerClient = Server.AcceptTcpClient();//보류중인 연결요청을 받아들임
                    rtbText.Invoke(AddText, "챗 상대 접속..");
                    myStream = SerClient.GetStream();//데이터를 보내고 받는 데 사용한 NetworkStream을 반환하여 myStream 개체에 대입

                    myRead = new StreamReader(myStream);//읽기 스트림
                    myWrite = new StreamWriter(myStream);//저장 스트림
                    this.ClientCon = true;//클라이언트 연결 허용

                    myReader = new Thread(Receive);//스레드를 이용하여 myReader개체를 생성
                    myReader.Start();
                }
                catch { }
            }
        }
        private void ServerStop() // 서버 모드 종료
        {
            this.Start = false;
            this.txtMessage.Enabled = false;
            this.txtMessage.Clear();
            this.btnSend.Enabled = false;
            this.tsbtnConn.Enabled = true;
            this.tsbtnDisconn.Enabled = false;
            this.ClientCon = false;
            if (!(myRead == null))
            {
                myRead.Close(); //StreamReader 클래스 개체 리소스 해제
            }
            if (!(myWrite == null))
            {
                myWrite.Close(); //StreamWriter 클래스 개체 리소스 해제
            }
            if (!(myStream == null))
            {
                myStream.Close(); //NetworkStream 클래스 개체 리소스 해제
            }
            //복사2 붙여넣기


            if (!(SerClient == null))
            {
                SerClient.Close(); //TcpClient 클래스 개체 리소스 해제
            }
            if (!(Server == null))
            {
                Server.Stop(); //TcpListen 클래스 개체 리소스 해제
            }
            if (!(myReader == null))
            {
                myReader.Abort(); //외부 스레드 종료
            }
            if (!(myServer == null))
            {
                myServer.Abort(); //외부 스레드 종료
            }
            if (!(AddText == null))
                rtbText.Invoke(AddText, "연결이 끊어졌습니다.");
        }

        private void Receive()
        {
            try
            {
                while (this.ClientCon)//클라이언트의 연결이 종료될 때까지 계속 실행
                {
                    if (myStream.CanRead)//스트림에서 데이터를 읽을 수 있는 경우
                    {
                        var msg = myRead.ReadLine();
                        var Smsg = msg.Split('&');//&를 기준으로 메시지 구분
                        if (Smsg[0] == "S001")//첫 구분자가  "S001“인 경우
                        {
                            this.tsslblTime.Text = Smsg[1];//상태바의 레이블에 날짜와 시간을 출력
                        }
                        else
                        {
                            if (msg.Length > 0)  //읽은 메시지가 있는 경우 
                            {
                                rtbText.Invoke(AddText, Smsg[0] + " : " + Smsg[1]);//MessageView()메서드를 이용화면에 출력
                            }
                            this.tsslblTime.Text = "마지막으로 받은 시각:" + Smsg[2];
                        }
                    }
                }
            }
            catch { }
        }

        private void tsbtnDisconn_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.SerClient.Connected)//연결중인 상태
                {
                    var dt = Convert.ToString(DateTime.Now);
                    myWrite.WriteLine(this.myName + "&" + "채팅 APP가 종료되었습니다." + "&" + dt);
                    myWrite.Flush();
                }
            }
            catch { }
            ServerStop();//서버종료
            this.설정ToolStripMenuItem.Enabled = true;

        }

        private void btnSend_Click(object sender, EventArgs e)
        {

            if (this.txtMessage.Text == "")
            {
                this.txtMessage.Focus();
            }
            else
            {
                Msg_send(); //Msg_send()함수 호출
            }


        }
        private void Msg_send()
        {
            try
            {
                var dt = Convert.ToString(DateTime.Now);
                //아이디 & 메시지 & 날짜시간을 보냄
                myWrite.WriteLine(this.myName + "&" + this.txtMessage.Text + "&" + dt);
                myWrite.Flush();
                //서버의 rtbText(채팅창)에 id와 메시지 출력
                MessageView(this.myName + ": " + this.txtMessage.Text);
                this.txtMessage.Clear();

            }
            catch
            {
                rtbText.Invoke(AddText, "데이터를 보내는 동안 오류가 발생하였습니다.");
                this.txtMessage.Clear();
            }
        }

        private void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13) //엔터 키를 누를때
            {
                e.Handled = true; //소리 없앰
                if (this.txtMessage.Text == "")
                {
                    this.txtMessage.Focus();
                }
                else
                {
                    Msg_send(); //Msg_send()함수 호출
                }
            }
        }

        private void txtMessage_TextChanged(object sender, EventArgs e)
        {
            //입력을 안하고 있던 상황에서 입력을 시작하는 경우
            if (TextChange == false)
            {
                TextChange = true;//입력을 하고 있다고 지정
                //정보전달의 암호: S001
                myWrite.WriteLine("S001" + "&" + "상대방이 메시지 입력중입니다." + "&" + " ");
                myWrite.Flush();
            }
            else if (this.txtMessage.Text == "" && TextChange == true)
            {//메시지를 입력하지 않은 경우
                TextChange = false;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            ServerStop();//서버종료
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }

}

교수님 강의 자료 보면서 따라하다가 크로스 쓰래드 문제가 생겨서 이렇게 햇는데 ;;  어디가 잘못된건지 못찾겠네요 ㅠㅠ 
혹시 아시는 분들 계신가요 ?
전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호