// don't use this in production
public static class SwitchContext
{
public static Awaiter Yield() { return new Awaiter(); }
public struct Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public Awaiter GetAwaiter() { return this; }
public bool IsCompleted { get { return false; } }
public void OnCompleted(Action continuation)
{
ThreadPool.QueueUserWorkItem((state) => ((Action)state)(), continuation);
}
public void GetResult() { }
}
}
// ...
await SwitchContext.Yield();
async Task<int> TestAsync()
{
///Initial Code
int m=3;
///Call the task
var X =foo4Async(m);
///Between
///Do something while waiting comes here
///..
var Result =await X;
///Final
///Some Code here
return Result;
}
5 回答
这很简单
为了使它成为一个等待的方法:
这里重要的是返回一个任务 . 该方法甚至不必标记为异步 . (只是进一步阅读它进入图片)
现在这可以称为
请注意,此处方法签名为
async
,因为该方法可能会将控制权返回给调用者,直到ExpensiveTaskAsync()
返回 . 而且,在这种情况下昂贵意味着耗时,如网络请求或类似的 . 要将大量计算发送到另一个线程,通常最好使用"old"方法,即System.ComponentModel.BackgroundWorker
用于GUI应用程序或System.Threading.Thread
.这是一个选项,但它实际上为您提供了异步代码的许多优点 . 有关更多详细信息,请参阅Stephen Toub's Should I expose asynchronous wrappers for synchronous methods?
一般来说,方法是不可取的,类型是 . 如果您希望能够编写类似
await MyMethod()
的内容,则MyMethod()
必须返回Task
,Task<T>
或自定义await
able类型 . 使用自定义类型是一种罕见的高级方案;使用Task
,您有几个选择:使用
async
和await
编写方法 . 这对于异步编写操作很有用,但它不能用于最内部的await
能够调用 .使用
Task
上的某个方法创建Task
,如Task.Run()
或Task.FromAsync()
.使用TaskCompletionSource . 这是最通用的方法,它可以用于从将来发生的任何事情中创建
await
able方法 .返回
Task
不是唯一的方法 . 您可以选择创建自定义awaiter(通过实现GetAwaiter
和INotifyCompletion),这是一个很好的读取:"Await anything" . 返回自定义awaiters的.NET API示例:Task.Yield()
,Dispatcher.InvokeAsync
.我有一些自定义awaiters here和here的帖子,例如:
是的,从技术上讲,您只需要从
async
方法返回Task
或Task<Result>
来实现一个等待的方法 .这支持Task-Based Asynchronous Pattern .
但是,有几种方法可以实现TAP . 有关详细信息,请参阅Implementing the Task-based Asynchronous Pattern .
(但当然,所有这些实现仍然会返回
Task
或Task<Result>
. )只需将您的方法转换为任务 . 像@Romiox我通常使用这个扩展
现在让我们说你有
void foo1()
void foo2(int i1)
int foo3()
int foo4(int i1)
...然后你可以像@Romiox一样声明你的[异步方法]
要么
...
现在你使用async并等待任何fooAsync,例如foo4Async