在MSDN上看到一句话:
The async-based approach to asynchronous programming is preferable to existing approaches in almost every case. In particular, this approach is better than the BackgroundWorker class for I/O-bound operations because the code is simpler and you don't have to guard against race conditions.
(几乎所有情况下,基于async的异步编程方式要优于现有的方式。特别是,在I/O绑定操作中,相比于BackgroundWorker类,async异步编程方式的代码更简单,且无需避免争用条件)
参考:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index
鉴于之前一直用的BackgroundWorker类来异步完成UI上的耗时操作,便想着改用await方式,看下效果。(其实很简单。。)
1.先写一个简单的通过BackgroundWorker实现异步耗时操作的例子,
程序模拟的效果是:窗体加载时,异步耗时操作(5秒)中获取一个字符串;然后UI线程将异步操作中获得的值赋给TextBox用于界面显示。
public partial class Form1 : Form
{
//m_text为界面上的一个文本框控件
private BackgroundWorker m_backgroundWorker = new BackgroundWorker();
private string m_stringValue;
public Form1()
{
InitializeComponent();
m_backgroundWorker.DoWork += AsyncWork;
m_backgroundWorker.RunWorkerCompleted += AsyncWorkCompleted;
}
private void Form1_Load(object sender, EventArgs e)
{
if (!m_backgroundWorker.IsBusy)
{
m_backgroundWorker.RunWorkerAsync();
}
}
private void AsyncWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(5000);//模拟一个耗时操作
m_stringValue = "异步操作中获取的字符串值";
}
private void AsyncWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
m_text.Text = m_stringValue;
}
}
2.改成await方式:
public partial class Form1 : Form
{
//m_text为界面上的一个文本框控件
private string m_stringValue;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
BindingTextValue();
}
private async void BindingTextValue()
{
await Task.Run(() =>
{
Thread.Sleep(5000);//模拟一个耗时操作
m_stringValue = "异步操作中获取的字符串值";
});
m_text.Text = m_stringValue;
}
}
对比两种写法,async-await方式的确简单,MSDN诚不我欺啊。
还有一个注意点:async-await异步编程是.NET Framework 4.5才有的,而BackgroundWorker在.NET Framework 2.0就已经有了。如果要在XP的.NET Framework4.0版本上使用,需要在NuGet下载微软提供的Microsoft.Bcl.Async包,且只支持XP SP3,并且需要下载补丁KB2468871。