一、线程
进程:我们每一个应用程序都是一个进程
而进程又是由多个线程组成的
前台线程: 只有所有的前台线程都关闭才能完成程序关闭。
后台线程: 只要所有的前台线程结束,后台线程自动结束。
1、如果线程执行的方法需要参数,那么要求这个参数必须是object类型。
//进程:我们每一个应用程序都是一个进程
//而进程又是由多个线程组成的
//电脑全部进程
//Process[] pros = Process.GetProcesses();
//foreach (var item in pros)
//{
// Console.WriteLine(item);
//}
//当前进程
//Console.WriteLine(Process.GetCurrentProcess().ToString());
//开启进程
//Process.Start("calc");
//Process.Start("mspaint");
//Process.Start("iexplore", "http://www.baidu.com");
//Thread.Sleep(10000);
//Console.WriteLine("hello world");
//打开指定文件
ProcessStartInfo psi = new ProcessStartInfo(@"C:\Users\Hey\Desktop\a.txt");
Process p = new Process();
p.StartInfo = psi;
p.Start();
Thread th;
private void button1_Click(object sender, EventArgs e)
{
//开启一个新的线程帮助我们执行Test方法
th = new Thread(Test);
//设置成后台线程
th.IsBackground = true;
//启动线程
th.Start();
}
void Test()
{
for (int i = 0; i < 10000; i++)
{
textBox1.Text = i.ToString();
}
}
private void Form1_Load(object sender, EventArgs e)
{
//取消对跨线程访问的检查
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//当关闭窗体的时候,同时关闭我的后台线程
if(th!=null)
{
//关闭线程
th.Abort();
//线程一旦关闭了,就不能在被打开了
}
}
练习 摇奖机
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
Thread th;
bool flag = false;
private void button1_Click(object sender, EventArgs e)
{
if(flag==false){
flag = true;
th = new Thread(GameStart);
th.IsBackground = true;
th.Start();
button1.Text = "暂停";
}
else
{
flag = false;
button1.Text = "开始";
}
}
public void GameStart()
{
Random r = new Random();
while (flag)
{
label1.Text = r.Next(0, 10).ToString();
label2.Text = r.Next(0, 10).ToString();
label3.Text = r.Next(0, 10).ToString();
}
}
private void Form2_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (th != null)
{
th.Abort();
}
}
}
二、事件
角色: 使对象或类具备通知能力的成员
事件使用: 用于对象或类间的动作协调与信息传递(消息推送)
事件模型的五个组成部分
1.事件的拥有者(event source,对象)
2.事件成员(event,成员)
3.事件的响应者(event subscriber,对象)
4.事件处理器(event handler,成员)——本质上是一个回调方法
5.事件订阅——把事件处理器与事件关联在一起,本质上是一种以委托类型为基础的"约定"
class MYForm
{
static void Main(string[] arg)
{
MForm mf = new MForm();
mf.Click += new EventHandler(mf.FormClicked);
//mf.Click += mf.FormClicked;
//mf.Click += delegate(object sender, EventArgs e)
//{
// mf.Text = DateTime.Now.ToString();
//};
//mf.Click += (sender, e) =>
//{
// mf.Text = DateTime.Now.ToString();
//};
mf.ShowDialog();
}
}
class MForm:Form
{
internal void FormClicked(object sender, EventArgs e)
{
this.Text = DateTime.Now.ToString();
}
}
三、socket
概念:socket的英文原义是“孔"或"插座”。作为进程通信机制,取后一种意思。通常也称作"套接字":用于描述IP地址和端口,是一个通信链的句柄。(其实就是两个程序通信用的。)
服务器端的Socket(至少需要两个)
一个负责接收客户端连接请求(但不负责与客户端通信)。每成功接收到一个客户端的连接便在服务端产生一个对应的负责通信的Socket
·在接收到客户端连接时创建.
为每个连接成功的客户端请求在服务端都创建一个对应的Socket(负责和客户端通信).
客户端的Socket
客户端Socket
·必须指定要连接的服务端地址和端口。
通过创建一个Socket对象来初始化一个到服务器端的TCP连接。
1.服务端
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
//创建一个负责监听的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//创建IP地址和端口号对象
IPAddress ip = IPAddress.Any;//IPAddress.Parse(txtServer.Text);
IPEndPoint point=new IPEndPoint(ip,Convert.ToInt32(txtPort.Text));
//让负责监听的Socket绑定IP地址跟端口号
socketWatch.Bind(point);
ShowMsg("监听成功");
//设置监听队列 排队
socketWatch.Listen(10);
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch);
}
/// <summary>
/// 等待客户端的连接 并且创建与之通信的socket
/// </summary>
Socket socketSend;
void Listen(Object o)
{
Socket socketWatch = o as Socket;
while (true)
{
try
{
//负责监听的Socket 来接受客户端的连接 创建跟客户端通信的Socket
socketSend = socketWatch.Accept();
//将远程连接的客户端的IP地址和端口号存入下拉框中
disSocket.Add(socketSend.RemoteEndPoint.ToString(),socketSend);
//将远程连接的客户端的IP地址和端口号存入下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");
Thread th = new Thread(Recive);
th.IsBackground = true;
th.Start(socketSend);
}
catch { }
}
}
//将远程连接的客户端的IP地址和Socket存入集合中
Dictionary<string,Socket> disSocket=new Dictionary<string,Socket>();
/// <summary>
/// 服务器端不停的接受 客户端发送来的消息
/// </summary>
/// <param name="o"></param>
void Recive( object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//客户端连接成功后,服务器应该接受客户端发来的消息
byte[] buffer = new byte[1024 * 1024 * 2];
//实际接受到的有效字节数
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
string str = Encoding.UTF8.GetString(buffer, 0, r);
ShowMsg(socketSend.RemoteEndPoint + ";" + str);
}
catch
{ }
}
}
void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 服务器给客户端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
string str = txtMsg.Text;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
List<byte> list = new List<byte>();
list.Add(0);
list.AddRange(buffer);
//将泛型集合转换为数组
byte[] newBuffer=list.ToArray();
//获得用户在下拉框中选中的IP地址
string ip = cboUsers.SelectedItem.ToString();
disSocket[ip].Send(newBuffer);
//socketSend.Send(buffer);
}
private void btnSelect_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = @"C:\Users\Hey\Desktop";
ofd.Title = "请选择要发送的文件";
ofd.Filter = "所有文件|*.*";
ofd.ShowDialog();
txtPath.Text = ofd.FileName;
}
private void btnSendFile_Click(object sender, EventArgs e)
{
//获得要发送文件的路径
string path = txtPath.Text;
using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024 * 1024 * 5];
int r = fsRead.Read(buffer, 0, buffer.Length);
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
//获得用户在下拉框中选中的IP地址
string ip = cboUsers.SelectedItem.ToString();
disSocket[ip].Send(newBuffer, 0, r + 1, SocketFlags.None);
}
}
/// <summary>
/// 发送震动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnZD_Click(object sender, EventArgs e)
{
byte[] buffer = new byte[1];
buffer[0] = 2;
disSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
}
}
}
2.客户端
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socketSend;
private void btnStart_Click(object sender, EventArgs e)
{
try
{
//创建负责通信的Socket
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(txtServer.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//获得要连接的远程服务器应用程序的IP地址和端口号
socketSend.Connect(point);
ShowMsg("连接成功");
//开启一个新的线程不停的接收服务器发来的消息
Thread th = new Thread(Recive);
th.IsBackground = true;
th.Start();
}
catch { }
}
void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
private void txtLog_TextChanged(object sender, EventArgs e)
{
}
/// <summary>
/// 客户端给服务器发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
string str=txtMsg.Text.Trim();
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
socketSend.Send(buffer);
}
/// <summary>
/// 不停的接受服务器发来的消息
/// </summary>
void Recive()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024 * 2];
//实际接收到的有效字符
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
//表示发送的文字消息
if (buffer[0] == 0)
{
string s = Encoding.UTF8.GetString(buffer, 1, r-1);
ShowMsg(socketSend.RemoteEndPoint + ":" + s);
}
else if (buffer[0] == 1)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @"C:\Users\Hey\Desktop";
sfd.Title = "请选择要保存的文件";
sfd.Filter = "所有文件|*.*";
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path,FileMode.OpenOrCreate,FileAccess.Write))
{
fsWrite.Write(buffer, 1, r - 1);
}
MessageBox.Show("保存成功");
}
else if (buffer[0] == 2)
{
ZD();
}
}
catch { }
}
}
//震动
void ZD()
{
for (int i = 0; i < 500; i++)
{
this.Location = new Point(200, 200);
this.Location = new Point(290, 290);
}
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
}
}