08 并行
并行串行计算比较
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace test07
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void bt_Click(object sender, RoutedEventArgs e)
{
long[] t1 = await Task.Run(() => Multiply(200, 18, 27));
tb.Text = string.Format("测试1(矩阵1:200x18,矩阵2:18x27),非并行用时{0}毫秒,并行用时{1}毫秒\n", t1[0], t1[1]);
long[] t2 = await Task.Run(() => Multiply(2000, 180, 270));
tb.Text += string.Format("测试1(矩阵1:2000x180,矩阵2:180x270),非并行用时{0}毫秒,并行用时{1}毫秒\n", t2[0], t2[1]);
long[] t3 = await Task.Run(() => Multiply(2000, 200, 300));
tb.Text += string.Format("测试1(矩阵1:2000x200,矩阵2:200x300),非并行用时{0}毫秒,并行用时{1}毫秒\n", t3[0], t3[1]);
}
/// <summary>
/// 传入行数和列数,初始化一个矩阵
/// </summary>
/// <param name="rows"></param>
/// <param name="cols"></param>
/// <returns></returns>
public static int[,] InitializeMatrix(int rows, int cols)
{
int[,] matrix = new int[rows, cols];
Random r = new Random();
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
matrix[i, j] = r.Next(100);
}
}
return matrix;
}
/// <summary>
/// 普通方法计算矩阵乘法
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public static void CommonCompute(int[,] a,int[,] b)
{
int arows = a.GetLength(0);
int acols = a.GetLength(1);
int bcols = b.GetLength(1);
int[,] result = new int[arows, bcols];
for(int i = 0; i < arows; i++)
{
for(int j = 0; j < bcols; j++)
{
int temp = 0;
for (int k = 0; k < acols; k++)
{
temp += a[i, k] * b[k, j];
}
result[i, j] = temp;
}
}
}
/// <summary>
/// 并行方法计算矩阵乘法
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public static void ParallelCompute(int[,] a, int[,] b)
{
int arows = a.GetLength(0);
int acols = a.GetLength(1);
int bcols = b.GetLength(1);
int[,] result = new int[arows, bcols];
Action<int> action = i =>
{
for (int j = 0; j < bcols; j++)
{
int temp = 0;
for (int k = 0; k < acols; k++)
{
temp += a[i, k] * b[k, j];
}
result[i, j] = temp;
}
};
//外循环并行执行
Parallel.For(0, arows, action);
}
/// <summary>
/// 计算矩阵乘法
/// </summary>
/// <param name="rows"></param>
/// <param name="cols"></param>
/// <param name="cols2"></param>
/// <returns></returns>
public static long[] Multiply(int rows,int cols,int cols2)
{
//初始化矩阵
int[,] a = InitializeMatrix(rows, cols);
int[,] b = InitializeMatrix(cols, cols2);
Stopwatch watch = new Stopwatch();
long[] timeElapsed = new long[2];
//串行
watch.Start();
CommonCompute(a, b);
watch.Stop();
timeElapsed[0] = watch.ElapsedMilliseconds;
//并行
watch.Restart();
ParallelCompute(a, b);
watch.Stop();
timeElapsed[1] = watch.ElapsedMilliseconds;
return timeElapsed;
}
}
}
09 新建WCF架构程序
- 1.新建WCF服务应用程序(或服务库),并设计服务程序。2.新建客户端程序(可以是wpf,控制台等),直接修改命名(~Client)。3.客户端程序添加服务引用(如果是在同一解决方案下,直接点“发现”,相当于把服务端的接口下载下来了,所以如果服务端修改程序的话(目前看包括接口的修改和接口实现的修改),必须要调试一下,“保存”,然后客户端需要重新添加服务引用。
- 1.新建WCF服务应用程序(或服务库),并设计服务程序。
[OperationContract]
string GetData(int value);
[OperationContract]
//启动进程
bool StartProcess(string processName);
[OperationContract]
//删除文件
bool DeleteFile(string path);
[OperationContract]
//获取文件信息
string ReadFile(string path);
[OperationContract]
//修改变量值
void Change(ref string s);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
方法实现:
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public bool StartProcess(string processName)
{
try
{
Process.Start(processName);
return true;
}
catch (Exception)
{
return false;
}
}
public bool DeleteFile(string path)
{
try
{
File.Delete(path);
return true;
}
catch (Exception)
{
return false;
}
}
public string ReadFile(string path)
{
string str, s;
str = "";
try
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
while ((s = sr.ReadLine()) != null)
{
str += s;
}
fs.Close();
sr.Close();
}
catch (Exception)
{
s = "读取失败";
}
return str;
}
public void Change(ref string s)
{
s = "changed";
}
- 步骤2
新建客户端,添加服务引用
界面设计:
功能实现;
private void bt_Click(object sender, RoutedEventArgs e)
{
Button currentbuttton = sender as Button;
string s = currentbuttton.Content.ToString();
if (s == "start")
{
StartProcess();
}
else if (s == "delete")
{
DeleteFile();
}
else if (s == "get")
{
ReadFile();
}
else if (s == "change")
{
Change();
}
}
//启动进程
public async void StartProcess()
{
Service1Client client = new Service1Client();
string processname = tbprocess.Text;
bool b = await Task<bool>.Run(() => client.StartProcess(processname));
if (b)
MessageBox.Show("启动进程成功!");
else
MessageBox.Show("启动进程失败!");
}
//删除文件
public async void DeleteFile()
{
Service1Client client = new Service1Client();
string path = tbdeleteFilePath.Text;
bool b = await Task<bool>.Run(() => client.DeleteFile(path));
if (b)
MessageBox.Show("删除成功!");
else
MessageBox.Show("删除失败!");
}
//获取文件信息
public async void ReadFile()
{
Service1Client client = new Service1Client();
string path = tbreaddFilePath.Text;
string s = await Task<string>.Run(() => client.ReadFile(path));
MessageBox.Show("读取内容:"+s);
}
//修改变量值
public async void Change()
{
Service1Client client = new Service1Client();
string s = tb.Text;
await Task.Run(() => client.Change(ref s));
tb.Text = s;
}
}
-
问题与解决
1.读取文件方法执行后无法打开文件
解决:忘了关闭流
2.删除文件时界面卡死
解决:文件路径里的“/”应该是换成“\”,然后意识到应该做异步编程。 -
一些比较复杂的类不能序列化(比如返回值是process类),可以自己新建类,给类加上数据协定,给类里面的属性也添加。
10 视频绘制
主要就是动态绘制类和静态绘制类,然后绑定到inkcanvas和radio button上。
基于矩形绘制来写视频绘制。
- 添加视频素材,直接把文件复制过来,右键,包含在项目中,对视频的属性设置为“复制到输出目录:始终复制”。
- 设计界面加上“视频”的按钮
- mainwindow.cs
private void RibbonRadioButton_Checked(object sender, RoutedEventArgs e)
{
RibbonRadioButton rrb = e.Source as RibbonRadioButton;
string rrbLabel = rrb.Label;
switch (rrbLabel)
{
case "球形":
myinkcanvas.selectShape = "球形";
InkEllipseDynamic myDynamic1 = new InkEllipseDynamic();
myinkcanvas.setDyanmic(myDynamic1);
break;
case "矩形":
myinkcanvas.selectShape = "矩形";
InkRectangleDynamic myDynamic2 = new InkRectangleDynamic();
myinkcanvas.setDyanmic(myDynamic2);
break;
case "图像":
myinkcanvas.selectShape = "图像";
//InkRectangleDynamic myDynamic2 = new InkRectangleDynamic();
//myinkcanvas.setDyanmic(myDynamic2);
break;
case "视频":
myinkcanvas.selectShape = "视频";
InkViedoDynamic myDynamic3 = new InkViedoDynamic();
myinkcanvas.setDyanmic(myDynamic3);
break;
}
myinkcanvas.setDyanmic(myDynamic3);
myinkcanvas
public void setDyanmic(DynamicRenderer d1)
{
this.DynamicRenderer = d1;
}
- 动态绘制类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;
namespace InkDrawExample.MyInks
{
class InkViedoDynamic : DynamicRenderer
{
public Point firstPoint;
public string uriString = @"Videos\Video1.wmv";
public MediaPlayer p;
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
base.OnStylusDown(rawStylusInput);
firstPoint = (Point)rawStylusInput.GetStylusPoints().First();
p = new MediaPlayer();
p.Open(new Uri(uriString, UriKind.Relative));
p.IsMuted = true; //把视频静音
p.MediaEnded += (s, e) => { p.Position = TimeSpan.Zero; };
p.Play();//开始播放视频
}
protected override void OnStylusMove(RawStylusInput rawStylusInput)
{
base.OnStylusMove(rawStylusInput);
StylusPointCollection stylusPoints = rawStylusInput.GetStylusPoints();
this.Reset(Stylus.CurrentStylusDevice, stylusPoints);
}
protected override void OnStylusUp(RawStylusInput rawStylusInput)
{
p.Stop();
p.Close();//关闭动态绘制时的媒体播放视频
base.OnStylusUp(rawStylusInput);
}
protected override void OnDraw(DrawingContext drawingContext, StylusPointCollection stylusPoints, Geometry geometry, Brush fillBrush)
{
Point lastPoint = (Point)stylusPoints.Last();
Vector v = Point.Subtract(lastPoint, firstPoint);
Rect rect = new Rect(firstPoint, v);
drawingContext.DrawVideo(p,rect);
}
}
}
因为视频加载播放会消耗资源,所以放在 OnStylusDown 里。
墨迹也会重新绘制视频,所以要在OnStylusUp 里把动态绘制时的视频关闭。
- 静态绘制类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;
namespace InkDrawExample.MyInks
{
class InkViedoStroke : Stroke
{
public static MediaPlayer p;
public string uriString = @"Videos\Video1.wmv";
public InkViedoStroke(StylusPointCollection stylusPoints)
: base(stylusPoints)
{
}
public static void CreateVideoPlayer(string uriString)
{
p = new MediaPlayer();
p.Open(new Uri(uriString, UriKind.Relative));
p.IsMuted = true;
p.MediaEnded += (s, e) => { p.Position = TimeSpan.Zero; };
p.Play();//开始播放视频
}
protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
{
Point firstPoint = (Point)this.StylusPoints.First();
Point lastPoint = (Point)this.StylusPoints.Last();
Vector v = Point.Subtract(lastPoint, firstPoint);
Rect rect = new Rect(firstPoint, v);
CreateVideoPlayer(uriString);
drawingContext.DrawVideo(p, rect);
}
}
}
先写DrawCore方法:根据动态绘制时的StylusPoints,设定好绘制矩形的形状, 用drawingContext.DrawVideo(p, rect); 绘制视频。所以需要一个meidaplayer,从动态绘制类里复制过来。
- 绑定到myinkcanvas
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
switch (selectShape)
{
case "球形":
this.Strokes.Remove(e.Stroke);
InkEllipseStroke stroke1 = new InkEllipseStroke(e.Stroke.StylusPoints);
this.Strokes.Add(stroke1);
break;
case "矩形":
this.Strokes.Remove(e.Stroke);
InkRectangleStroke stroke2 = new InkRectangleStroke(e.Stroke.StylusPoints);
this.Strokes.Add(stroke2);
break;
case "图像":
this.Strokes.Remove(e.Stroke);
//构造静态呈现对象
//添加到this.Strokes.Add();
break;
case "视频":
this.Strokes.Remove(e.Stroke);
InkViedoStroke stroke3 = new InkViedoStroke(e.Stroke.StylusPoints);
this.Strokes.Add(stroke3);
break;
}
}
public void setDyanmic(DynamicRenderer d1)
{
this.DynamicRenderer = d1;
}
11.WCF和HTTP文件传输
- 服务端
.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace downloadfiles
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
[ServiceContract]
public interface IService1
{
[OperationContract]
List<string> GetFilesInfo();
[OperationContract]
Stream DownloadStream(string fileName);
}
}
.svc.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace downloadfiles
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
public class Service1 : IService1
{
public static List<string> filesInfo;
public static string path;
public List<string> GetFilesInfo()
{
if (filesInfo == null)
{
filesInfo = new List<string>();
path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "download");
DirectoryInfo di = new DirectoryInfo(path);
var q = di.GetFiles();
foreach(var i in q)
{
filesInfo.Add(string.Format("{0},{1}", i.Name, i.Length));
}
}
return filesInfo;
}
public Stream DownloadStream(string fileName)
{
string filePath = System.IO.Path.Combine(path, fileName);
try
{
FileStream imageFile = File.OpenRead(filePath);
return imageFile;
}
catch (IOException EX)
{
throw EX;
}
}
}
}
web.congfig 修改使传输容量更大
<bindings>
<basicHttpBinding>
<!--67108864的含义是64MB,这是HTTP每次传输允许的最大值(不指定时默认值为64KB)
用HTTP实现时,如果希望下载大文件(例如2GB),需要先将文件按64MB切分,
客户端分别下载后,最后再将其合并为一个文件。
另外,也可以用TCP提供下载功能,用TCP实现时可通过配置直接下载不大于4GB的文件,
具体实现见MSDN中的相关说明-->
<binding name="HttpStreaming" maxReceivedMessageSize="671088640" transferMode="Streamed"/>
</basicHttpBinding>
</bindings>
- 客户端
界面设计
using Client.ServiceReference1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Client
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public static string[] filesInfo;
public MainWindow()
{
InitializeComponent();
Service1Client client = new Service1Client();
filesInfo = client.GetFilesInfo();
foreach (string i in filesInfo)
{
string[] split = i.Split(',');
lb.Items.Add(string.Format("文件名:{0},字节长度:{1}", split[0], split[1]));
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int n = lb.SelectedIndex;
if (n != -1)
{
string[] s = filesInfo[n].Split(',');
string fileName = s[0];
string fileSize = s[1];
Service1Client client = new Service1Client();
Stream imageFile = client.DownloadStream(fileName);
tb.Text += "正在下载" + fileName + "\n";
//读取
byte[] buffer = new byte[1024];//设置缓冲区
string path = @"E:\study\大二下\网络编程\作业\WCF和HTTP文件传输\downloadfiles\" + fileName;
//目标文件流
FileStream fsNew = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
int num;
int sum = 0;
while ( (num=imageFile.Read(buffer, 0, buffer.Length)) > 0)
{
sum += num;
//写入目标文件流
fsNew.Write(buffer, 0, num);
}
//一定要关闭流,如果没有关闭,在此程序外就无法对文件进行操作
imageFile.Close();
fsNew.Close();
tb.Text += "下载完成,共下载" + sum + "字节," + "文件保存到" + path;
}
}
}
}
app.config 修改使传输容量更大
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxReceivedMessageSize="67108864" transferMode="Streamed"/>
</basicHttpBinding>
</bindings>
12.实验五:WCF和TCP的消息通信练习
- App.config的配置
<!-- Service Endpoints -->
<!-- 参考修改endpoint ,注意 替换为自身的服务协议 命名控件.接口文件名-->
<endpoint address="net.tcp://localhost:51888/Service1/" binding="netTcpBinding" contract="TestChatServer.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
- 服务端
接口:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace TestChatServer
{
//需要服务端实现的协定
[ServiceContract(Namespace = "TestChatServer",
//SessionMode = SessionMode.Required,
CallbackContract = typeof( IService1Callback))]
public interface IService1
{
[OperationContract(IsOneWay = true)]
void Login(string userName);
[OperationContract(IsOneWay = true)]
void Logout(string userName);
[OperationContract(IsOneWay = true)]
void Talk(string userName, string message);
// TODO: 在此添加您的服务操作
}
//需要客户端实现的接口
public interface IService1Callback
{
[OperationContract(IsOneWay = true)]
void ShowLogin(string loginUserName);
[OperationContract(IsOneWay = true)]
void ShowLogout(string userName);
[OperationContract(IsOneWay = true)]
void ShowTalk(string userName, string message);
[OperationContract(IsOneWay = true)]
void Updateinfo(List<string> users,int usercount);
}
// 使用下面示例中说明的数据约定将复合类型添加到服务操作。
// 可以将 XSD 文件添加到项目中。在生成项目后,可以通过命名空间“TestChatServer.ContractType”直接使用其中定义的数据类型。
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
构造User类和CC类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestChatServer
{
class User
{
public string UserName { get; set; }
public readonly IService1Callback callback;
public User(string userName, IService1Callback callback)
{
this.UserName = userName;
this.callback = callback;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestChatServer
{
class CC
{
//保存连接的用户
public static List<User> Users { get; set; }
public static User GetUser(string userName)
{
User user = null;
foreach (var v in Users)
{
if (v.UserName == userName)
{
user = v;
return user;
}
}
return user;
}
}
}
接口实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace TestChatServer
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Service1”。
public class Service1 : IService1
{
public Service1()
{
if (CC.Users == null)
{
CC.Users = new List<User>();
}
}
public void Login(string userName)
{
OperationContext context = OperationContext.Current;
IService1Callback callback = context.GetCallbackChannel<IService1Callback>();
User newUser = new User(userName, callback);
CC.Users.Add(newUser);
foreach (var user in CC.Users)
{
//发给每个线上的用户
user.callback.ShowLogin(userName);
}
SendInfoToAllUsers();
}
/// <summary>用户退出</summary>
public void Logout(string userName)
{
User logoutUser = CC.GetUser(userName);
foreach (var user in CC.Users)
{
//不需要发给退出用户
if (user.UserName != logoutUser.UserName)
{
user.callback.ShowLogout(userName);
}
}
CC.Users.Remove(logoutUser);
logoutUser = null; //将其设置为null后,WCF会自动关闭该客户端
SendInfoToAllUsers();
}
public void Talk( string userName, string message)
{
foreach (var user in CC.Users)
{
//发给每个线上的用户
user.callback.ShowTalk(userName, message);
}
}
// <summary>将当前在线情况发送给所有用户</summary>
private void SendInfoToAllUsers()
{
int userCount = CC.Users.Count;
List<string> users = new List<string>();
foreach (var item in CC.Users)
{
string str = item.UserName;
users.Add(str);
}
foreach (var user in CC.Users)
{
user.callback.Updateinfo(users, userCount);
}
}
}
}
- 客户端
MainWindow 做主界面,新建 clientwindow 窗口作客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestChatClient
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btn1_Click(object sender, RoutedEventArgs e)
{
StartWindow("西西", 580, 300);
StartWindow("瓜瓜", 0, 0);
}
private void StartWindow(string userName, int left, int top)
{
ClientWindow w = new ClientWindow();
w.Left = left;
w.Top = top;
w.UserName = userName;
w.Owner = this;
w.Closed += (sender, e) => this.Activate();
w.Show();
}
private void btn2_Click(object sender, RoutedEventArgs e)
{
ClientWindow w = new ClientWindow();
w.Owner = this;
w.Closed += (sendObj, args) => this.Activate();
w.Show();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using TestChatClient.ServiceReference1;
namespace TestChatClient
{
/// <summary>
/// ClientWindow.xaml 的交互逻辑
/// </summary>
public partial class ClientWindow : Window,IService1Callback
{
public string UserName
{
get { return textBoxUserName.Text; }
set { textBoxUserName.Text = value; }
}
private Service1Client client;
public ClientWindow()
{
InitializeComponent();
this.Closing += Window_Closing;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
ChangeState(btnLogin, true, btnLogout, false);
if (client != null)
{
client.Logout(UserName);
client = null;
}
}
private static void ChangeState(Button btnStart, bool isStart, Button btnStop, bool isStop)
{
btnStart.IsEnabled = isStart;
btnStop.IsEnabled = isStop;
}
private void AddColorMessage(string str, SolidColorBrush color)
{
TextBlock t = new TextBlock();
t.Text = str;
t.Foreground = color;
listBoxMessage.Items.Add(t);
}
//单击登录按钮引发的事件
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
this.Cursor = Cursors.Wait;
UserName = textBoxUserName.Text;
InstanceContext context = new InstanceContext(this);
client = new ServiceReference1.Service1Client(context);
try
{
client.Login(textBoxUserName.Text);
ChangeState(btnLogin, false, btnLogout, true);
}
catch (Exception ex)
{
MessageBox.Show("与服务端连接失败:" + ex.Message);
return;
}
this.Cursor = Cursors.Arrow;
}
private void btnLogout_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
//单击发送按钮引发的事件
private void btnSend_Click(object sender, RoutedEventArgs e)
{
client.Talk( UserName, textBoxSend.Text);
textBoxSend.Text = "";
}
//在对话文本框中按回车键时引发的事件
private void textBoxTalk_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
client.Talk(UserName, textBoxSend.Text);
}
textBoxSend.Text = "";
}
#region 实现IService1Callback接口
public void ShowLogin(string loginUserName)
{
AddColorMessage(string.Format("[{0}],进入群聊", loginUserName), Brushes.Black);
}
public void ShowLogout(string userName)
{
AddColorMessage(string.Format("[{0}],离开群聊", userName), Brushes.Black);
}
public void ShowTalk(string userName, string message)
{
AddColorMessage(string.Format("[{0}]说:{1}", userName, message), Brushes.Black);
}
public void Updateinfo(string[] users, int usercount)
{
listBoxUsers.Items.Clear();
tb.Text = "在线人数:" + usercount;
foreach (var item in users)
{
TextBlock t = new TextBlock();
t.Text = item;
Foreground = Brushes.Black;
listBoxUsers.Items.Add(t);
};
}
#endregion
}
}