二,线程的同步和异步
如果看到我关于委托应用(二)的朋友应该发现了this.Invoke(delegate) 的用法,这是实际是线程的调用,跨线程调用的使用 ,和new delegate().Invoke() 是不一样的,但是都可去调用委托的同步异步!
概念
同步:发起调用,必须等着完成后,才能进入下一行。
异步:发起调用,不用等着完成,直接进入下一行,原来的操作也会有新的执行流来完成。
一,线程同步
1,同步方法卡界面,UI线程(主线程)忙于计算,无法响应别的操作
2, 同步方法慢,只有一个线程参与计算
3,但是在实际开发中反而是单进程单线程的应有比价多,像node,redis就是典型的单进程单线程!
这里,我开始控制台,同时开启了一个窗体,窗体页面执行了一个很耗时间的计算,那么在执行的过程中,由于是同步方法,所以form1则假死了,无法进行其他操作!这就是同步 !
代码如下
class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Console.WriteLine("开启线程之旅!,打开窗体");
}
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine();
Console.WriteLine(" 同步方法开始,线程ID为 {0}", Thread.CurrentThread.ManagedThreadId);
for (int i = 1; i <= 6; i++) //特意执行了6次
{
string name = string.Format("[第{0}_{1}", "button1_Click]", i);
this.DoSomethingLong(name);
}
Console.WriteLine(" button1_Click 同步方法结束,线程ID为 {0} ", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine();
}
#region PrivateMethod
/// <summary>
/// 一个耗时耗资源的测试方法
/// </summary>
/// <param name="name"></param>
private void DoSomethingLong(string name)
{
Console.WriteLine("--start,线程发起者:{0},ID:{1},time:{2} --",
name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("HHmmss:fff"));
long lResult = 0;
for (int i = 0; i < 1_000_000_000; i++)
{
lResult += i;
}
Console.WriteLine("**end,线程发起者:{0},ID: {1} ,time:{2},sum: {3} **",
name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("HHmmss:fff"), lResult);
}
#endregion
}
2多线程异步
特点
1,异步多线程不卡界面,计算交给子线程,UI线程闲置,可以响应别的操作,这些场景可以使用
Winform–文件上传/订单提交—异步多线程
Winform–网络检测, 数据发包–异步多线程
MVC—用户注册发邮件/发短信—异步多线程发邮件
2,异步多线程方法快
但并不是越多越好, 因为:
1资源有限
2线程调度损耗
线程并不是越多越好,除非真的需要用资源换性能
3,异步多线程的无序性:
启动无序:非阻塞,同一时间申请线程,但是操作系统无法掌控
执行时间不确定:因为CPU的调度是OS完成的(线程优先级也只是影响分配策略)
结束无序:以上叠加就是的
多线程是很难掌控,但是也有办法(顺序控制,回调/等待/信号量)
多线程开发时,一定不要通过延迟一下这种方式来控制顺序(非常不安全的做法)
接下来感受异步执行
无序体现出来了,同时这个这个form1是可以控制的,是可移动的说明线程没有阻塞
代码如下:
private void button2_Click(object sender, EventArgs e)
{
Console.WriteLine();
Console.WriteLine("异步方法开始,线程ID为 {0}", Thread.CurrentThread.ManagedThreadId);
// Action<string> action = new Action<string>(DoSomethingLong);
Action<string> action = DoSomethingLong;
for (int i = 1; i <= 5; i++)
{
string name = string.Format("[{0}_第{1}次", "button2_Click]", i);
AsyncCallback callback = new AsyncCallback(Call);
IAsyncResult Result = action.BeginInvoke(name, callback, "aaa"); //这个aaa就是回调中的 AsyncState 的值,很多时候就是用这个参传值给回调使用的
// action.EndInvoke(Result); //调用完成之后接收回调
// action.Invoke(name);// 同步方法
}
Console.WriteLine(" button2_Click 异步方法结束,线程ID为 {0} ", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine();
}
void Call(IAsyncResult async)
{
if (async.IsCompleted)
{
Console.WriteLine("回调显示状态" + async.AsyncState); //调用成功之后执行回调
}
}
暂时写到这里!欢迎指点!