如何等待Task启动?

时间:2015-10-14 08:40:30

标签: c# task

我该如何等待任务开始。以下代码失败:

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?

4 个答案:

答案 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.IsCompletedTask.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...");
        }
    }