问题出在输出
当前输出为
等待工作
工作开始
延迟开始
工作完成
延迟结束
想去哪里
等待工作
工作开始
延迟开始
延迟结束
工作完成
private static Task _task;
public static void Main(string[] args)
{
Call().Wait();
}
private static async Task Call()
{
_task = new Task(async () => { await Pause(); });
var timer = new Timer();
timer.Interval = 10000;
timer.Enabled = true;
timer.AutoReset = false;
timer.Elapsed += Timer_Elapsed;
Console.WriteLine("job waiting");
await _task;
Console.WriteLine("job done");
Console.ReadKey();
}
public static async Task Pause()
{
Console.WriteLine("Delay started");
await Task.Delay(10000);
Console.WriteLine("Delay ended");
}
private static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("job starting");
_task.Start();
}
答案 0 :(得分:1)
之所以这样做,是因为我需要在某个时间点创建一个任务,但稍后再开始
在这种情况下,合适的工具是Func<Task>
,而不是Task
构造函数。 The Task
constructor should never, ever be used。
在这种情况下,由于Task
构造函数无法理解async
委托,因此您的输出不理想。因此,传递给async
构造函数的Task
委托被视为async void
,这使得等待它变得不可行。
解决方法是使用支持async
的工具。在这种情况下,为async-compatible delegate。由于Task
对象在计时器事件触发之前不存在,因此您还需要将该对象作为“信号”传递给另一个方法,这有点尴尬。大多数现实世界的代码都不需要这样做:
private static Func<Task> _func;
private static TaskCompletionSource<Task> _taskSignal = new TaskCompletionSource<Task>();
private static async Task Call()
{
_func = Pause;
var timer = new Timer();
timer.Interval = 10000;
timer.Enabled = true;
timer.AutoReset = false;
timer.Elapsed += Timer_Elapsed;
Console.WriteLine("job waiting");
var task = await _taskSignal.Task; // Get the Task instance representing Pause
await task; // Wait for Pause to finish
Console.WriteLine("job done");
Console.ReadKey();
}
public static async Task Pause()
{
Console.WriteLine("Delay started");
await Task.Delay(10000);
Console.WriteLine("Delay ended");
}
private static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("job starting");
var task = _func(); // Start Pause running
_taskSignal.TrySetResult(task); // Pass the Pause task back to Main
}
答案 1 :(得分:-1)
一种解决方案是使任务主体同步。换句话说:
_task = new Task(async () => { await Pause(); });
...执行此操作:
_task = new Task(() => { Pause().Wait(); });
如果要使其保持异步,则必须找到一种方法来等待任务主体。这可以通过创建Task<Task>
并等待任务的结果而不是主要任务本身来实现:
_task = new Task<Task>(async () => { await Pause(); });
//...
await _task.Result;