正确使用Async / Await

时间:2014-08-12 07:28:06

标签: c# async-await .net-4.5

这是我对async / await的实现,但我不确定我是否正确执行。

代码按预期工作,但我希望有人查看这些小代码来指出任何错误。

public class DbUtils
{

    public static List<string> GetDataSources()
    {
        //I have removed some logic from here as it's not important to my question
        List<string> names = new List<string>();
        names = SomeClass.SomeLongSystemMethod();
        return names;
    }

    public static async Task<List<string>> GetDataSourcesAsync()
    {
        //This is a place where I have my doubts
        return await Task.Run(() =>
        {
            return GetDataSources();
        });
    }
}

public class SomeOtherClass
{
    private async void BT_RefreshServerName_Click(object sender, EventArgs e)
    {
        CB_ServerName.DataSource = await DbUtils.GetDataSourcesAsync();
    }
}

编辑:

我的新版代码看起来像这样。

public class SomeOtherClass
{
    private async void BT_RefreshServerName_Click(object sender, EventArgs e)
        {
            try
            {
                BT_RefreshServerName.Enabled = false;

                //.ConfigureAwait(true) (this is a default) is to attempt to
                //marshal the continuation back to the original context as the
                //result is used to update UI.                    
                CB_ServerName.DataSource = await Task.Run(
                 () => DbUtils.GetDataSources()).ConfigureAwait(true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK);
            }
            finally
            {
                BT_RefreshServerName.Enabled = true;
            }
        }
    }
}

public class DbUtils
{

    public static List<string> GetDataSources()
    {
        //Some logic

        List<string> names = new List<string>();
        names = SomeClass.SomeLongSystemMethod();
        return names;
    }
}

1 个答案:

答案 0 :(得分:4)

GetDataSourcesAsync的实现被称为“async over sync”,并且通常被认为是反模式(虽然公平地说,它没有“同步过度那么糟糕”异步“)。它至少会起作用,但是如果你实际上没有真正的async操作,那么使用工作线程(通常是线程池),后面跟{实际上没有任何区别{1}} / Invoke返回UI线程(进行UI更新)。

如果这是问题,它会起作用。

现在,如果BeginInvoke实际使用了GetDataSourcesAsync数据访问方法; 然后这将是伟大的代码。在那个事件中你不需要*Async,顺便说一句。

另外:在事件处理程序中添加一些异常处理。