Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正确使用异步/等待_C#_Async Await_.net 4.5 - Fatal编程技术网

C# 正确使用异步/等待

C# 正确使用异步/等待,c#,async-await,.net-4.5,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&g

这是我对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();
    }
}
公共类DbUtils
{
公共静态列表GetDataSources()
{
//我从这里删除了一些逻辑,因为这对我的问题并不重要
列表名称=新列表();
names=SomeClass.SomeLongSystemMethod();
返回姓名;
}
公共静态异步任务GetDataSourcesAsync()
{
//这是我怀疑的地方
返回等待任务。运行(()=>
{
返回GetDataSources();
});
}
}
公共类其他类
{
私有异步无效BT\u刷新服务器名称\u单击(对象发送方,事件参数e)
{
CB_ServerName.DataSource=await DbUtils.getdatasourceasync();
}
}
编辑:

我的新版本代码如下所示

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;
    }
}
public类SomeOtherClass
{
私有异步无效BT\u刷新服务器名称\u单击(对象发送方,事件参数e)
{
尝试
{
BT_RefreshServerName.Enabled=false;
//.ConfigureAwait(true)(这是默认值)用于尝试
//将延续封送回原始上下文作为
//结果用于更新用户界面。
CB_ServerName.DataSource=等待任务。运行(
()=>DbUtils.GetDataSources()).ConfigureAwait(true);
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message,“Exception”,MessageBox按钮.OK);
}
最后
{
BT_RefreshServerName.Enabled=true;
}
}
}
}
公共类DbUtils
{
公共静态列表GetDataSources()
{
//一些逻辑
列表名称=新列表();
names=SomeClass.SomeLongSystemMethod();
返回姓名;
}
}

GetDataSourcesAsync的实现被称为“async over sync”,通常被认为是一种反模式(虽然公平地说,它没有“sync over async”那么糟糕)。它至少可以工作,但是如果您没有真正的
async
操作,那么使用工作线程(通常是线程池),然后调用
/
/
BeginInvoke
返回UI线程(执行UI更新)并没有什么区别

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

现在,如果
getdatasourceasync
实际使用了
*Async
数据访问方法;那将是很棒的代码。您不需要
任务。顺便说一句,在这种情况下运行


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

GetDataSourcesAsync的实现被称为“async over sync”,通常被认为是一种反模式(尽管公平地说,它没有“sync over async”那么糟糕)。它至少可以工作,但是如果您没有真正的
async
操作,那么使用工作线程(通常是线程池),然后调用
/
/
BeginInvoke
返回UI线程(执行UI更新)并没有什么区别

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

现在,如果
getdatasourceasync
实际使用了
*Async
数据访问方法;那将是很棒的代码。您不需要
任务。顺便说一句,在这种情况下运行


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

这个问题似乎离题了,因为它属于@RemusRusanu,我不知道还有一个单独的部分。谢谢你提供的信息。下一次我将使用codereview部分。如果在等待任务之后您没有做任何事情,您可以简单地返回任务。这将有助于优化代码,因为它不需要创建代理任务。因此,GetDataSourcesAsync可以更改为
return Task.FromResult(GetDataSources())
然后删除上的异步修饰符function@JLevett谢谢这正是我想要的答案。欢呼这个问题似乎离题了,因为它属于@RemusRusanu,我不知道还有一个单独的部分。谢谢你提供的信息。下一次我将使用codereview部分。如果在等待任务之后您没有做任何事情,您可以简单地返回任务。这将有助于优化代码,因为它不需要创建代理任务。因此,GetDataSourcesAsync可以更改为
return Task.FromResult(GetDataSources())
然后删除上的异步修饰符function@JLevett谢谢这正是我想要的答案。干杯我知道我可以用线程池。当我使用.NET3.5时,我试图摆脱用来处理UI操作的额外代码。正如你所建议的,我将放弃使用这种反模式。你能看一下我在问题中的编辑并复习一下新版本吗?我在这个问题上尽量少用代码,所以这里没有异常处理;)@我真的不确定编辑是否与我的建议一致。。。我的建议是不要使用“async over sync”,您仍在这样做。我的建议是使用异步数据访问API,但你没有这样做。在阅读了更多关于这个主题的文章(和其他文章)之后,我明白了为什么我没有抓住你的重点。然而,我仍然对在这种情况下“(..)使用异步数据访问API感到困惑。我把“异步数据访问API”理解为.Wait()/configurewait()等方法,但我想我已经被这个主题淹没了,因为我今天刚刚切换到.NET 4.5。我在编辑中更改了代码,以匹配当前的实现,该实现按预期工作,我认为现在的代码要好得多。@RafałS no、
.Wait()
.configurewait()
不在他们的范围之内