C# 如何正确创建等待的方法

C# 如何正确创建等待的方法,c#,async-await,C#,Async Await,我正在写一些值得期待的方法,我在互联网上找到了很多方法。所以我来到这里是为了了解每一条道路上到底发生了什么,以及是否必须消除某些道路 据我所知,有两种等待的方法: 调用其他等待的方法的方法: 及 但我最近发现: 例3 公共任务GetFooAsync() { TaskCompletionSource tcs=新的TaskCompletionSource(); SetResult(TrulyGetFoo()); 返回tcs.Task; } 如果我理解正确,等待的方法并不总是在另一个线程上运行??

我正在写一些值得期待的方法,我在互联网上找到了很多方法。所以我来到这里是为了了解每一条道路上到底发生了什么,以及是否必须消除某些道路

据我所知,有两种等待的方法:

调用其他等待的方法的方法: 及

但我最近发现:

例3 公共任务GetFooAsync() { TaskCompletionSource tcs=新的TaskCompletionSource(); SetResult(TrulyGetFoo()); 返回tcs.Task; }
如果我理解正确,等待的方法并不总是在另一个线程上运行???我猜第三个示例提供了这种机制(但是如何?我只在第三个示例中看到同步代码),而示例1和2总是在工作线程上运行


可能还有其他方法可以编写可等待的方法,所以请让我了解它们。

我将其用于处理数据库的异步事件

private async void btnSave_Click(object sender, EventArgs e)
    {

             success = await someClass.someMethod(some args);

    }
someMethod是这样的任务:

public static async Task<someObject> someMethod(args)
    {
       //do something here
    }
公共静态异步任务方法(args)
{
//在这里做点什么
}

简短的版本是:任何返回任务的内容都可以在
异步
代码块中等待

public async Task MyAsyncMethod()
{
    // do some stuff
    await TrulyAsyncFoo();
    // do some other stuff
    return;
}
如果等待异步调用是该方法所做的唯一事情,那么您只需返回任务本身,它将在“上游”等待:

至于在异步方法中调用同步(非异步)代码,则没有什么意义。只需像普通代码一样调用它:

public async Task MyAsyncMethod()
{
    MySyncMethod();
    await TrulyAsyncFoo();
    MyOtherSyncMethod();
}
执行
Task.Run(()=>Foo())
几乎总是一种代码味道,表明您没有正确地执行异步/等待。编写异步代码与编写多线程代码不同。异步只是告诉编译器需要等待某个网络或IO绑定任务完成的一种好方法

总而言之:

  • wait允许您并行编写异步和同步代码
  • 异步应仅用于等待网络或IO绑定的任务,而不是计算绑定的任务
  • 异步方法应始终返回
    Task
    Task
  • 避免
    异步无效
  • 避免在ASP.NET和其他线程化应用程序中使用
    task.Wait()
    task.Result
    ,除非您知道自己在做什么
例如,我看到[
Task.Run
wrappers环绕同步代码]

。我有一篇博文解释了这一点

据我所知,async/await关键字是无用的,可以避免

是的,但是

我最近发现[
TaskCompletionSource
]

如注释中所述,您的代码示例仍然是同步的

要使其异步,代码应该启动一些操作并返回
TaskCompletionSource.Task
。随后,每当该操作完成时,您的完成处理程序应调用
TaskCompletionSource.SetResult
(或类似方法)。有关示例,请参见或


TaskFactory.fromsync
也是
TaskCompletionSource
的包装器,用于。

另一种方式:公共任务getfooancy(){return trulygetfooancy();}当然可以。这个例子我简化得太多了,你的话是对的。我将编辑我的问题以澄清!“我只在第三个示例中看到同步代码”-它是完全同步的。任务将返回“已完成”状态。在这种情况下,您可以对返回任务执行相同的操作。FromResult(TrulyGetFoo())
。这是如何回答上面的问题的?
除非绝对必要,否则应避免使用async void
。async/Wait/Task的一个好资源是Stephen Cleary的博客
,如果等待异步调用是该方法唯一做的事情,你可以简单地返回任务本身
>正如我在问题的评论中对鲁福爵士所说的那样,我简化了太多的示例。我刚刚编辑了我的问题,想找个更好的例子<代码>通常不需要Task.Run(()=>Foo())或其他复杂语法。这几乎总是一种代码味道,您没有像您所说的那样正确地进行异步/等待。那么,如果我仍然需要它呢?来自Sir Rufo link:
过去使用过Task的开发人员倾向于在异步世界中以同样的方式使用它(这是错误的)
我想我不止一次落入了陷阱。这两个链接真的很有趣。谢谢@我稍微澄清了我的答案。调用同步方法不需要
任务。运行
-您具体想做什么?我以两种不同的方式实现了一个接口,其中包含返回任务的方法。一个实现是使用幕后等待的方法,所以我没有问题。另一个实现只使用不可等待的方法,那么如何编写这个实现呢?只需使用
Task.FromResult()
?我正在处理的应用程序是WPF应用程序。我不想在通话中冻结我的用户界面。我正在阅读您的
任务之旅
文章,由鲁福爵士在另一个答案中提供。这一点,加上你答案中的所有链接,我今天有一堆相互询问的阅读资料。
Task.Run((Foo)TrulyGetFoo); // I don't know if the cast is required at any time but in my code, it was
public Task<Foo> GetFooAsync()
{
    TaskCompletionSource<Foo> tcs = new TaskCompletionSource<Foo>();
    tcs.SetResult(TrulyGetFoo());
    return tcs.Task;
}
private async void btnSave_Click(object sender, EventArgs e)
    {

             success = await someClass.someMethod(some args);

    }
public static async Task<someObject> someMethod(args)
    {
       //do something here
    }
public async Task MyAsyncMethod()
{
    // do some stuff
    await TrulyAsyncFoo();
    // do some other stuff
    return;
}
public Task MyAsyncMethod()
{
    return TrulyAsyncFoo();
}
public async Task MyAsyncMethod()
{
    MySyncMethod();
    await TrulyAsyncFoo();
    MyOtherSyncMethod();
}