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;
}
线程中
--------------------编程问答-------------------- 不要使用CheckForIllegalCrossThreadCalls
Invoke(settext, new object[] { textBox1, "你的内容!" });
用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, () =>--------------------编程问答-------------------- private void button1_Click(object sender, EventArgs e)
{
picBox.Image = imageList1.Images["logoico_offline.ico"];
});
{
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"));*/
--------------------编程问答--------------------
大量的IO操作还有网络请求最好单开线程。
补充:.NET技术 , C#