原文:同步,异步,多线程,你怎么看?[原创]
讲解同步与异步的帖子多如牛毛,个人的理解,简单地说同步就是串行,异步就是并行。同步的情况下,A调用B,A等B执行完成后接着执行,自始至终只有一个线程在运行;而异步时,A调用B,B执行,A也继续执行,这个过程中有两个线程在运行。本文通过winform下的一个实例讲解同步与异步的差别,本文的例子很简单,适合初学者。
1.同步
大家应该经常碰到这种情况,点击界面上某个按钮或者某个控件后界面卡死的情况,个人觉得其中一个原因可能是主线程的问题,界面主线程在后台处理其他任务,没法同时响应用户的操作。看一个最简单的例子,界面如下:
代码:
private void btnCalc_Click(object sender, EventArgs e)
{
int sum = Calc(100);
rtxtMain.Text = "calc over, result is " + sum;
MessageBox.Show("计算完成", "提示");
}
private int Calc(int n)
{
int sum = 0;
Thread.Sleep(TimeSpan.FromSeconds(20));
for (int i = 0; i < n; i++)
{
sum += i;
}
return sum;
}
很明显,使用这种方法时点击按钮后界面就卡住,直到后台方法执行完才响应。原因是只有主线程在运行,那么咱们再重新起一个新线程,可以自己另起一个线程,或者使用.NET提供的异步方法。
2.异步
.NET异步时重新从线程池中启动了一个线程,本例中这个线程负责执行后台的方法,界面主线程继续响应用户的操作。线程池线程执行完后台方法后弹出提示框提示主线程工作已做完。代码如下:
public delegate int CalcEventHandler(int n); //定义委托
public partial class MainFrm : Form
{
public MainFrm()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false; //禁用非法跨线程调用检查
}
private void btnCalc_Click(object sender, EventArgs e)
{
CalcEventHandler mycalc = new CalcEventHandler(Calc);
AsyncCallback async = new AsyncCallback(OnComplete); //回调方法
mycalc.BeginInvoke(100, async, "this is your data" ); //执行异步
}
private int Calc(int n)
{
int sum = 0;
Thread.Sleep(TimeSpan.FromSeconds(20));
for (int i = 0; i < n; i++)
{
sum += i;
}
return sum;
}
//异步完成后执行的回调方法
private void OnComplete(IAsyncResult asycResult)
{
AsyncResult result = (AsyncResult)asycResult;
CalcEventHandler del = (CalcEventHandler)result.AsyncDelegate; //向下转换
int sum = del.EndInvoke(asycResult); //获取返回值
string data = result.AsyncState != null ? result.AsyncState.ToString() : string.Empty; //获取传递的数据
rtxtMain.Text = "calc over, 结果为 " + sum + ", 传递信息为 " + data;
MessageBox.Show("计算完成","提示"); //提示主线程
}
}
结果如下:
这样,界面不会出现卡死的情况,可以提高用户体验。当然这只是一个简单的例子。
还有一种方法就是,自己另外启一个线程,代码如下:
private void btnCalc_Click(object sender, EventArgs e)
{
Thread tr = new Thread(new ThreadStart(Calc)); //启动新线程
tr.Start();
}
private void Calc() //重载方法
{
Calc(100);
}
private int Calc(int n)
{
int sum = 0;
Thread.Sleep(TimeSpan.FromSeconds(5));
for (int i = 0; i < n; i++)
{
sum += i;
}
rtxtMain.Text = "calc over, 结果为 " + sum; //提示移到这里
MessageBox.Show("计算完成", "提示");
return sum;
}
小结:
1.这个例子很简单,用于了解同步和异步的区别和作用。
2.同步和异步跟为委托和多线程是相关联的,有兴趣的朋友继续学习委托和多线程相关知识。
本文写的很简单,谢谢你的阅读,如果有好的建议或方法,欢迎留言,一起交流~~