如何等待Task启动
本文关键字:Task 启动 等待 何等待 | 更新日期: 2023-09-27 18:17:32
如何等待任务启动?以下代码失败:
var asyncmethod = ...a Task<TReturn>, with .Start() called on it...;
int waitcounter = 0;
while (!asyncmethod.Wait(1000))
{
waitcounter++;
Log("waiting very long...");
}
ret = asyncmethod.Result;
asyncmethod.Wait(1000)按预期等待1秒,但任务处于WaitingToRun状态,并且在Wait()ing时永远不会开始运行。另一方面,当. result被调用时,它将开始运行。如何让它运行而不调用。result ?
任务处于WaitingToRun状态,并且在Wait()ing
时不会开始运行。
当一个任务处于WaitingToRun
状态时,这意味着它已经准备好开始运行,只是在等待它的调度上下文可用,所以它可以被调度和运行(正如我在我的博客中所描述的)。
由于Wait(1000)
完成后任务仍然处于此状态,那么假定任务正在等待调用线程使用的调度上下文,因此在该线程空闲之前无法调度。
任务。Result可以触发任务内联并执行任务,但显然Wait()不能。
.Result
和.Wait()
都将允许任务内联,但是.Wait(x)
当然不能,因为它必须遵守超时。
然而,.Result
和.Wait()
都不能保证内联——在编写可靠的代码时记住这一点很重要。
代码不应该中断,不管任务是被安排在"当前"还是一个单独的线程上。
这是一个极其难以满足的要求。你确定你需要这个吗?
最简单的解决方案是异步等待:Task<T> asyncmethod = ...;
int waitcounter = 0;
while (await Task.WhenAny(Task.Delay(1000), asyncmethod) != asyncmethod)
{
waitcounter++;
Log("waiting very long...");
}
ret = await asyncmethod;
等待任务完成,使用:
asyncmethod.Start();
asyncmethod.Wait(); // not needed in most cases
// but if used, the task is completed at this point.
var ret = asyncmethod.Result; // automatically waits for the task to be completed
但基本上,等待是不必要的,除非你有理由这样做。从Task<TResult>.Result
-docs:
此属性的get访问器确保异步操作完成后返回。曾经的结果计算是可用的,它被存储并将返回立即调用Result。(从msdn)
不太确定为什么要这样做,但这可以在不阻塞调用线程的情况下实现使用Task.IsCompleted
和Task.Delay
:
public async Task FooAsync()
{
var waitCounter = -1;
var task = Task.Run(() => { });
do
{
waitCounter++;
await Task.Delay(1000);
}
while (!task.IsCompleted)
}
如果Task
需要超过1000ms才能完成,则此代码段将调用Log
一次。
private async static void StartTask()
{
Task<object> asyncmethod = ... ;
LogDurationTooLong(asyncmethod, 1000);
var result = await asyncmethod;
}
/// <summary>
/// Logs if a task takes too long to complete.
/// </summary>
/// <param name="asyncmethod">The task to reference.</param>
/// <param name="duration">The duration after which a log entry is made.</param>
private async static void LogDurationTooLong(Task asyncmethod, int duration)
{
Task completedTask = await Task.WhenAny(Task.Delay(duration), asyncmethod);
if (completedTask != asyncmethod)
{
Log("waiting very long...");
}
}