我该如何等待任务开始。以下代码失败:
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秒,但Task处于WaitingToRun状态,并且在Wait()时将永远不会开始运行。另一方面,当调用.Result时,它将开始运行。如何让它在没有调用的情况下运行.Result?
答案 0 :(得分:1)
任务处于WaitingToRun状态,并且在Wait()ing
时永远不会开始运行
当任务在the WaitingToRun
state, that means it is ready to start running and is just waiting for its scheduling context to be available时,可以安排并运行(正如我在博客中描述的那样)。
由于任务在Wait(1000)
完成后仍处于此状态,因此可能是任务正在等待调用线程使用的调度上下文,因此不能计划直到该帖子空闲。
Task.Result可以触发任务内联和执行任务,但显然Wait()不能。
.Result
和.Wait()
都允许内联任务,但当然.Wait(x)
不能,因为它必须遵守超时。
然而,neither .Result
nor .Wait()
will guarantee inlining - 在编写可靠代码时要牢记这一点非常重要。
代码不应该中断,无论任务是否安排在&#34;当前&#34;或者一个单独的线程。
这是一个非常难以满足的要求。你确定需要吗?
最简单的解决方案是异步等待:
Task<T> asyncmethod = ...;
int waitcounter = 0;
while (await Task.WhenAny(Task.Delay(1000), asyncmethod) != asyncmethod)
{
waitcounter++;
Log("waiting very long...");
}
ret = await asyncmethod;
答案 1 :(得分:0)
等待使用以下任务完成任务:
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
- 文档:
此属性的get访问器可确保异步 返回前操作完成。一旦结果了 计算可用,它被存储并将被返回 立即在以后调用Result。 (from msdn)
答案 2 :(得分:0)
不确定为什么要这样做,但这可以在不使用Task.IsCompleted
和Task.Delay
阻止调用线程的情况下实现:
public async Task FooAsync()
{
var waitCounter = -1;
var task = Task.Run(() => { });
do
{
waitCounter++;
await Task.Delay(1000);
}
while (!task.IsCompleted)
}
答案 3 :(得分:0)
如果Log
完成时间超过1000毫秒,此代码段会一次调用Task
。
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...");
}
}