使用await和async运行long方法时释放UI线程

时间:2014-01-08 10:15:58

标签: c# multithreading asynchronous async-await

我开始探索异步并等待来自c#5.0的关键字,所以我使用winforms进行了一些测试,但现在我陷入了困境:

我的观点是从数据库运行查询,而查询未完成,我想在表单上显示加载gif。

这是查询数据库的方法:

public static async Task<List<string>> GetItensFromDatabase()
    {
        List<string> names = new List<string>();

        using (ServerConn)
        {
            ServerConn.Open();
            SqlCommand cmd = new SqlCommand("Select * From Names", ServerConn);

            var ds = new DataSet();
            var adapter = new SqlDataAdapter(cmd);
            adapter.Fill(ds); // this call lasts about 1 minute

            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                names.Add(dr["Name"].ToString());
            }
        }
        return names;
    }

我在这里称之为:

private async void button1_Click(object sender, EventArgs e)
    {
        List<string> itens = null;
        itens = await AsyncMethods.GetItensFromDatabase(); // I want that the form dont be stuck here

        ShowItensInListView(itens);
    }

现在我在旋转的窗体上有一个无所不在的加载图像gif,直到调用方法GetItensFromDatabase,当方法运行时,gif停止,当方法完成gif开始再次旋转时。

那么,有些方法可以在GetItensFromDatabase方法运行时保持gif旋转吗?

1 个答案:

答案 0 :(得分:2)

您可以在await方法中使用async关键字,但由于没有等待操作,您应该使用{{1}在方法中明确创建Task }:

TaskFactory

编辑:正如@mmarques所指出的,另一个(更好的)解决方案是使用public static Task<List<string>> GetItensFromDatabase() { return Task.Factory.StartNew<List<string>>(() => { List<string> names = new List<string>(); using (ServerConn) { ServerConn.Open(); SqlCommand cmd = new SqlCommand("Select * From Names", ServerConn); var ds = new DataSet(); var adapter = new SqlDataAdapter(cmd); adapter.Fill(ds); // this call lasts about 1 minute foreach (DataRow dr in ds.Tables[0].Rows) { names.Add(dr["Name"].ToString()); } } return names; }); } 而不是SqlDataReader。原因是SqlDataAdapterSqlDataReader个方法可用 - 这意味着您不需要使用async来阻止线程池中的新线程,您可以使用TaskFactoryasync

await