当前位置:编程学习 > C#/ASP.NET >>

C# 跨线程修改窗口控件 僵死问题

各位大侠好

本菜鸟在写 socket作业的时候遇到了一个很奇怪的问题,描述如下:

背景:
1、要求实现用户端和服务器端,服务器端能检测用户名密码,能echo用户端发送的文本信息
2、选择使用C#实现要求,服务端基于一个窗体类进行编写,由于UI在执行函数的时候会假死,所以选择新创建一个进程,通过跨线程修改主窗体中的label来达成显示信息的目的;
3、进行研究性编写的时候,遇到跨线程调用的问题,查阅MSDN得知可用代理解决,但是编写了代理之后,第一次跨线程修改可以成功,但是第二次调用代理进行跨线程修改时程序卡死,包括UI也不能动了;
4、当3的情况出现以后,我试着改用CheckForIllegalCrossThreadCalls = false;然后直接用this.label_test_display.Text = textBuffer;来进行修改,同样出现了第一次执行正常第二次执行卡死的问题,将label改成textBox问题依旧;

作业要交不上了,求各位大侠帮帮小弟吧,感激不尽!!!!

附:服务器端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Test_Sever : Form
    {
        Socket server;
        delegate void CrossSetText(string text);//为甚么第二次就不能用了?
        string textBuffer;

        private BackgroundWorker bkw1;

        private void bkw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(textBuffer!=null)
                this.label_test_display.Text += textBuffer;
        }

        public Test_Sever()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;

        }

     

        private void appendText1(string text)
        {
            if (this.label_test_display.InvokeRequired)
            {
                CrossSetText set = new CrossSetText(appendText1);
                this.Invoke(set, new object[] { text });
            }
            else
            {
                this.label_test_display.Text += text;
            }
        }

        public void Show2()
        {
            //Show();
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipend = new IPEndPoint(IPAddress.Any, 44444);

            server.Bind(ipend);
            server.Listen(10);
            while (true)
            {


                textBuffer = "/n等待连接/n";
                this.label_test_display.Text += textBuffer;

              //  this.backgroundWorker1.RunWorkerAsync();
                Socket client = server.Accept();

                IPEndPoint clipos = (IPEndPoint)client.RemoteEndPoint;
                string temp = clipos.Address + ":" + clipos.Port + "已连接\n";
            //    appendText1(temp);

                textBuffer = temp;
              //  this.backgroundWorker1.RunWorkerAsync();
                this.label_test_display.Text = textBuffer;

                Console.WriteLine(temp);
                byte[] data = new byte[1024];

                client.Receive(data,1024,SocketFlags.None);

                String content = Encoding.UTF8.GetString(data);

                textBuffer = content;
               // this.backgroundWorker1.RunWorkerAsync();
                //appendText1(content);
                this.label_test_display.Text = textBuffer;

                byte[] sendbuffer = Encoding.UTF8.GetBytes("ACCESS GRANTED");
                client.Send(sendbuffer,sendbuffer.Length,SocketFlags.None);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
             new Thread(new ThreadStart(Show2)).Start();
           /* server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipend = new IPEndPoint(IPAddress.Any, 27019);

            server.Bind(ipend);
            server.Listen(10);

            label_test_display.Text = "等待连接/n";
            Socket client = server.Accept();

            IPEndPoint clipos = (IPEndPoint)client.RemoteEndPoint;
            label_test_display.Text += clipos.Address + ":" + clipos.Port + "已连接\n";
            byte[] data = new byte[1024];

            client.Receive(data);

            String content = Encoding.UTF8.GetString(data);

            label_test_display.Text += content;

            client.Send(Encoding.UTF8.GetBytes("ACCESS GRANTED"));*/
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {

        }
        private void backgroundWorker1_RunWorkerCompleted(
            object sender,
            RunWorkerCompletedEventArgs e)
        {
            if (textBuffer != null)
                this.label_test_display.Text += textBuffer;
        }

    }
} --------------------编程问答-------------------- 不要使用CheckForIllegalCrossThreadCalls 
用委托实现。


        private delegate void Settext(TextBox obj, string txt);
        private void settext(TextBox obj, string txt)
        {
            obj.Text = txt;
        }

线程中

    Invoke(settext, new object[] { textBox1, "你的内容!" });
--------------------编程问答-------------------- 不要使用CheckForIllegalCrossThreadCalls
用Control.Invoke()或Form.Invoke()//其实一样的……
记得先用invokerequired判断。这样就不必考虑跨线程访问控件的问题了。
封装成2个扩展方法很好用。以前百度的……

static public void UiThread(this Form form, Action action)
        {
            if (form.InvokeRequired)
            {
                form.Invoke(action);
                return;
            }
            action.Invoke();
        }

        static public void UiThread(this Control c, Action action)
        {
            if (c.InvokeRequired)
            {
                c.Invoke(action);
                return;
            }
            action.Invoke();
        }

调用:
 UiThreadMsg.UiThread(this, () =>
            {
                picBox.Image = imageList1.Images["logoico_offline.ico"];
            });
--------------------编程问答--------------------  private void button1_Click(object sender, EventArgs e)
        {
             new Thread(new ThreadStart(Show2)).Start();
           /* server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipend = new IPEndPoint(IPAddress.Any, 27019);

            server.Bind(ipend);
            server.Listen(10);

            label_test_display.Text = "等待连接/n";
            Socket client = server.Accept();  <---这里是会让线程挂起的,也就是造成UI假死的情况

            IPEndPoint clipos = (IPEndPoint)client.RemoteEndPoint;
            label_test_display.Text += clipos.Address + ":" + clipos.Port + "已连接\n";
            byte[] data = new byte[1024];

            client.Receive(data); <---这里是会让线程挂起的,也就是造成UI假死的情况

            String content = Encoding.UTF8.GetString(data);

            label_test_display.Text += content;

            client.Send(Encoding.UTF8.GetBytes("ACCESS GRANTED"));*/
        }


所以最好这一部份也要用线程或用Socket的异步处理
label_test_display.Text = "等待连接/n";
            Socket client = server.Accept();  <---这里是会让线程挂起的,也就是造成UI假死的情况

            IPEndPoint clipos = (IPEndPoint)client.RemoteEndPoint;
            label_test_display.Text += clipos.Address + ":" + clipos.Port + "已连接\n";
            byte[] data = new byte[1024];

            client.Receive(data); <---这里是会让线程挂起的,也就是造成UI假死的情况

            String content = Encoding.UTF8.GetString(data);

            label_test_display.Text += content;

            client.Send(Encoding.UTF8.GetBytes("ACCESS GRANTED"));*/
--------------------编程问答--------------------
引用 3 楼 wyd1520 的回复:
private void button1_Click(object sender, EventArgs e)
        {
             new Thread(new ThreadStart(Show2)).Start();
           /* server = new Socket(AddressFamily.InterNetwork,……

大量的IO操作还有网络请求最好单开线程。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,