JAY21
63
2018-10-22 17:58:40
0
276

윈폼에서 다른쓰레드가 컨트롤 만드는 방법 질문드립니다.


메인 쓰레드에서 메세지 루프가 돌아서 GUI를 업데이트를 한다는것은 이해했습니다.

그래서 다른 쓰레드에서 컨트롤을 접근할때 invoke 메서드를 사용한다는것도 이해했고

그렇게 해서 메인쓰레드에서 이미 만들어진 컨트롤을 제어하는데는 성공했습니다.

문제가 되는 시나리오는 이렇습니다.

로그인 폼에서는 로그인이 성공하면 다른 폼을 만듭니다. 프로파일 폼인데

그 프로파일 폼에서는 2가지 스레드를 생성합니다

하나는 메세지를 서버로 보내는 스레드

하나는 메세지를 서버에서 받는 스레드입니다

아래 코드는 프로파일 폼이 생성되면서 쓰레드를 생성하는 부분입니다.

 public void initData(string id, TcpClient tcp, string friendlist)
        {
            // 이것이 call되는 시점은 생성자call된 이후 시점.
            myId = id;
            connection = tcp;
            stream = tcp.GetStream();
            int idx = 0;
            int cnt = 0;
            while (true)
            {
                idx = friendlist.IndexOf(' ');
                if (idx == -1)
                {
                    break;
                }
                string name = friendlist.Substring(0, idx);
                friendlist = friendlist.Substring(idx);
                friendlist = friendlist.TrimStart(' ');
                BtnChatMemManager.getInstance().dicProfileList.Add(name, new ProFileEX(new Size(300, 50), new Point(0, 50 * cnt + 1), name, this));
                // this.Size = new Size(300, 500);
                //lstCprofile.Add(new ProFileEX(new Size(300,50), new Point(0, 0), "정으니",this));
                cnt++;
            }


            Thread recv = new Thread(new ThreadStart(takeMsgFromServ));
            Thread send = new Thread(new ThreadStart(sendMsgToServ));
            recv.Start();
            send.Start();
            //test

        }

recv쓰레드에서는 

메세지를 받고 처리하는 클래스가 하나 돌아가고

아래 코드는 처리하는 부분입니다.

  void processData()
        {

            while (getdatalength() > 8) // 메세지를 2개이상 q받았을시도 처리 
            {
                TcpHeader head = this.getheader();
                if(getdatalength() < head.msgsize)
                {
                    break;
                }
                string strmsg = Encoding.Unicode.GetString(m_field, m_rear + 1 + m_headsize, (int)head.msgsize - m_headsize);
                subData((int)head.msgsize);

                string[] tok = strmsg.Split(' ');
                string Id = tok[0];
                string msg = tok[1];

                if (BtnChatMemManager.getInstance().dicProfileList.ContainsKey(Id))
                {

                    ChatLstButton btn = ((ChatLstButton)BtnChatMemManager.getInstance().dicChatList[Id]);
                    if (btn.InvokeRequired)
                        btn.Invoke(btn.myDelegate, msg);
                    else
                        btn.getMsg(msg);

                }
                else
                {

                    ProfileForm profile = (ProfileForm)BtnChatMemManager.getInstance().dicFormList["profileForm"];

                    ChatLstButton btn = ((ChatLstButton)BtnChatMemManager.getInstance().dicChatList[Id]);
                    if (btn.InvokeRequired)
                        btn.Invoke(btn.myDelegate, msg);
                    else
                        btn.getMsg(msg);

                }
            }

        }
    

profile.invoke(profile.createbtn)

이런식으로 버튼과 같은 방식으로 델리게이트를호출해도 이 스레드에서 새로운 버튼을 만들면

그 버튼은 이 쓰레드에 핸들이 남는거 같습니다.

그래서 여기서 생성된 버튼은 Invokerequired자체가 false로 되어있습니다.

profile폼에서는 제가 마든 커스텀 탭 컨트롤이 있는데요



private void ChatMouseBtnClicked(object sender, EventArgs arg)//탭버튼
        {
            SButton btn = (SButton)sender;
            if (btn == bn_chat)
            {
                bn_profile.forChatAction();
                Pn_tab.Controls.Clear();
                foreach (KeyValuePair<string, Control> entry in BtnChatMemManager.getInstance().dicChatList)
                {
                    Pn_tab.Controls.Add(entry.Value);
                }
            }
            else
            {
                bn_chat.forChatAction();
                Pn_tab.Controls.Clear();
                foreach (KeyValuePair<string, Control> entry in BtnChatMemManager.getInstance().dicProfileList)
                {
                    Pn_tab.Controls.Add(entry.Value);
                }
            }
        }



이렇게 탭을 누르면 컨트롤을 넣어주는 식으로 작동하는데요.

여기서 다른 쓰레드에서 생성된 컨트롤을 넣어주면 예외가 발생합니다..


질문을 간단히 말씀드리자면

다른쓰레드에서 메인스레드에게 컨트롤을 만들라고하게 하고 싶습니다..

오늘 하루 종일 이 문제 검색하느라 시간 다 보냈네요... ㅜㅜ

0
0
  • 답변 0

  • 로그인을 하시면 답변을 등록할 수 있습니다.