2015-10-14 81 views
0

我该如何等待任务开始。下面的代码失败:如何等待任务启动?

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并且永远不会开始运行等待()ING时。另一方面,当调用.Result时,它将开始运行。如何让它在没有调用的情况下运行.Result?

+3

'伺机asyncmethod()'? – ieaglle

+1

请向我们展示您的问题的最小完整重现,而不是伪代码。你为什么要创建一个任务并立即用'Wait'阻止它? –

+0

为什么不使用“Thread.Sleep(1000);”代替? – Rariolu

回答

1

的任务是在国家WaitingToRun,永远不会开始运行时,wait()就

当一个任务是在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 - 在编写可靠代码时务必牢记这一点。

不管是否在“当前”或单独的线程上调度任务,代码都不应该中断。

这是一个非常困难的要求,以满足。你确定你需要吗?

最简单的解决办法是异步等待:

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

但基本上,等待的不是neccesary,除非你有一个原因。从Task<TResult>.Result -docs:

此属性的get访问保证异步 操作完成后才返回。一旦 计算的结果可用,它将被存储,并将在稍后调用Result时立即返回 。 (from msdn

+0

这确实总会产生结果,但我想等待(1000),所以我可以记录它需要很长时间。但显然Wait()并不完全像.Result的方式是.Result获取Task执行fase,而Wait()不会那样做。例如你可以在一个尚未开始的任务上永远等待()... – Edwin

+1

这是真的,但这通常也意味着'.Result'永远不会返回。 – nozzleman

+0

is sugegst试图将您的问题改为您实际尝试实现的目标。也许背景工作者会更适合你的需要。但那需要更多信息 – nozzleman

0

真的不知道为什么你这样做,但可以不使用Task.IsCompletedTask.Delay阻塞调用线程来实现:

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

这个片段将调用Log一个时间,如果Task需要超过1000毫秒才能完成。

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..."); 
     } 
    } 
+0

这只会记录一次。 –

+0

@YuvalItzchakov它只记录一次设计。问题不清楚,所以我抛出了我的解释。 – Gusdor