Ars*_*ray 4 .net c# async-await
我正在尝试实现一个自定义awaiteable执行await Thread.SleepAsync()而不创建任何额外的线程.
这是我得到的:
class AwaitableThread : INotifyCompletion
{
public AwaitableThread(long milliseconds)
{
var timer = new Timer(obj => { IsCompleted = true; }, null, milliseconds, Timeout.Infinite);
}
private bool isCompleted = false;
public bool IsCompleted
{
get { return isCompleted; }
set { isCompleted = value; }
}
public void GetResult()
{}
public AwaitableThread GetAwaiter() { return this; }
public void OnCompleted(Action continuation)
{
if (continuation != null)
{
continuation();
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是睡眠的工作方式:
static async Task Sleep(int milliseconds)
{
await new AwaitableThread(milliseconds);
}
Run Code Online (Sandbox Code Playgroud)
问题是这个函数不可避免地返回,即使在OnCompleted,IsCompleted仍然是假的.
我究竟做错了什么?
Jon*_*eet 10
完全实现生产使用的等待模式是一件棘手的事情 - 您需要捕获执行上下文等等.Stephen Toub关于此的博文有更多细节.在许多情况下,它更容易捎带Task<T>或Task潜在使用TaskCompletionSource.例如,在您的情况下,您可以编写如下的等效内容Task.Delay:
public Task MyDelay(int milliseconds)
{
// There's only a generic TaskCompletionSource, but we don't really
// care about the result. Just use int as a reasonably cheap version.
var tcs = new TaskCompletionSource<int>();
Timer timer = new Timer(_ => tcs.SetResult(0), null, milliseconds,
Timeout.Infinite);
// Capture the timer variable so that the timer can't be garbage collected
// unless the task is (in which case it doesn't matter).
tcs.Task.ContinueWith(task => timer = null);
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
你现在await可以完成这项任务,就像你可以等待结果一样Task.Delay.