如何等待任务开始?

How to wait for Task to start?

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

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 时永远不会启动 运行ning。另一方面,当调用 .Result 时,它将开始 运行ning。如何在不调用 .Result 的情况下将其设置为 运行?

等待任务完成使用:

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-文档:

The get accessor for this property ensures that the asynchronous operation is complete before returning. Once the result of the computation is available, it is stored and will be returned immediately on later calls to Result. (from msdn)

不太确定为什么要这样做,但这可以在不阻塞调用线程的情况下使用 Task.IsCompletedTask.Delay:

实现
public async Task FooAsync()
{
    var waitCounter = -1;
    var task = Task.Run(() => { });
    do
    {
        waitCounter++;
        await Task.Delay(1000);
    }
    while (!task.IsCompleted)
}

如果 Task 需要超过 1000 毫秒才能完成,此代码段将调用 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...");
        }
    }

the Task is in the state WaitingToRun and will never start running when 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 can trigger task inlining and execute task, but apparently Wait() cannot.

.Result.Wait() 都允许内联任务,但是 .Wait(x) 当然不能,因为它必须遵守超时。

但是,neither .Result nor .Wait() will guarantee inlining - 在编写可靠代码时牢记这一点很重要。

the code shouldn't break, regardless of if the task is scheduled on the "current" or a separate thread.

这是一个极难满足的要求。您确定需要吗?

最简单的解决方案是异步等待:

Task<T> asyncmethod = ...;
int waitcounter = 0;
while (await Task.WhenAny(Task.Delay(1000), asyncmethod) != asyncmethod)
{
  waitcounter++;
  Log("waiting very long...");
}
ret = await asyncmethod;