1. 程式人生 > >在WPF中使用C#6.0新特性async與await

在WPF中使用C#6.0新特性async與await

在C#6.0中 使用async與await 關鍵字很容易的實現非同步程式設計,而且程式碼可讀性比較高,很容易理解。這裡舉例的是從資料庫中讀取10w行資料。 下面看程式碼:

xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="800">
    <Grid>
        <StackPanel Margin="10">
            <TextBox x:Name="tb" Width="600" Height="40"></TextBox>
            <GroupBox Header="載入資料">
                <DataGrid x:Name="dg" Margin="20" Width="600" Height="500" AutoGenerateColumns="True">
                </DataGrid>
            </GroupBox>
            <ProgressBar x:Name="pb" Width="500" Height="30" IsIndeterminate="False" Minimum="0" Maximum="100"></ProgressBar>
            <TextBlock x:Name="tbTime"></TextBlock>
            <Button x:Name="btnClick" Width="120" Height="30" Content="click" Click="btnClick_Click"></Button>
        </StackPanel>
    </Grid>
</Window>

佈局很簡單,使用tb來顯示非同步開始與結束;使用Datagrid 來承載資料;pb顯示進度條;tbTimer來顯示計算的耗時時間。讀取資料:
 /// <summary>
        /// 當前執行緒排程器
        /// </summary>
        private readonly Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;


  /// <summary>
        /// 讀取資料
        /// </summary>
        public string SlowDude()
        {
            // 查詢資料到DataSet
            DataSet dt = DbHelperSQL.ExecuteDataSet("select * from DevelopRecord", null);
            this._dispatcher.BeginInvoke(new Action(() =>
            {
                dg.ItemsSource = dt.Tables[0].DefaultView;
            }));
            return "";
        }

如果不使用非同步方式,直接呼叫SlowDude方法會出現介面卡頓,使用者體驗不是很好。讀取資料非同步方法:
   /// <summary>
        /// 非同步讀取資料
        /// </summary>
        public async void SlowDudeAsync()
        {
            var slowTask = Task<string>.Factory.StartNew(() => SlowDude());
            tb.Text = "開始非同步\r\n";
            pb.IsIndeterminate = true;
            // 計算耗時
            System.Diagnostics.Stopwatch stop = new System.Diagnostics.Stopwatch();
            stop.Start();
            await slowTask;
            tb.Text += "非同步結束";
            pb.IsIndeterminate = false;
            stop.Stop();
            tbTime.Text = "耗時:" + stop.ElapsedMilliseconds + "ms";
        }

這裡的async關鍵字標示SlowDudeAsync為非同步方法,該方法不僅可以返回void也可以返回Task<TResult>型別,例如:
     public async Task<string> GetStrAsync(Uri uri)
        {
            using (var client = new HttpClient())
            {
                var str = await client.GetStringAsync(uri).ConfigureAwait(false);
                return str;
            }
        }

GetStrAsync方法返回string型別的Task,獲取返回結果:
Task<string> task = GetStrAsync(new Uri("http://www.baidu.com"));
var result = task.Result;

點選載入呼叫載入事件:
   private void btnClick_Click(object sender, RoutedEventArgs e)
        {
            SlowDudeAsync();
        }

顯示效果: