Task.WaitAny 退化案例行为
Task.WaitAny degenerate case behaviour
我找不到关于 Task.WaitAny()
在以下情况下的行为的任何文档:
- 给定一个空的任务数组。
- 给定一组任务,其中一个已经完成。
- 给定一系列任务,所有任务都已完成。
我的假设是 2 和 3 会立即 return(#3 选择一个任意索引到 return,可能是第一个或最后一个取决于实现细节但不能保证。)和我希望 1 到 return 是真的吗?
一些简短的单元测试似乎证实了这一点...以下全部通过。
如果有人能找到这种行为的一些正式文件,我会很高兴看到它。 (哪怕只是为了提高自己下次自己定位的能力!)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using System.Threading;
namespace TANTest.Threading
{
[TestFixture]
public class MetaTaskTests
{
private const int SafeTimeOutMillisecs = 1000;
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_NewTaskCompletes()
{
var task = new Task(() => { });
task.Start();
Thread.Sleep(10);
Assert.That(task.IsCompleted, Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_EmptySetOfTasks_WaitsProceed()
{
var tasks = new List<Task>();
Task.WaitAny(tasks.ToArray());
Task.WaitAll(tasks.ToArray());
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_EmptySetOfTasks_WaitsGiveExpectedOutputs()
{
var tasks = new List<Task>();
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.EqualTo(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfCompletedTasks_WaitsProceed()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.ForEach(task => task.Start());
Thread.Sleep(10);
Task.WaitAny(tasks.ToArray());
Task.WaitAll(tasks.ToArray());
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfCompletedTasks_WaitsGiveExpectedOutputs()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.ForEach(task => task.Start());
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.GreaterThan(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfUnstartedTasks_WaitsDontProceed()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.EqualTo(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.False);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfTasksWithOneCompleted_AnyProceedsAndOutputsIndex()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.First().Start();
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray()), Is.GreaterThan(-1));
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfTasksWithOneCompleted_AllTimesOutWithExpectedOutput()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.First().Start();
Thread.Sleep(10);
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.False);
}
}
}
我找不到关于 Task.WaitAny()
在以下情况下的行为的任何文档:
- 给定一个空的任务数组。
- 给定一组任务,其中一个已经完成。
- 给定一系列任务,所有任务都已完成。
我的假设是 2 和 3 会立即 return(#3 选择一个任意索引到 return,可能是第一个或最后一个取决于实现细节但不能保证。)和我希望 1 到 return 是真的吗?
一些简短的单元测试似乎证实了这一点...以下全部通过。 如果有人能找到这种行为的一些正式文件,我会很高兴看到它。 (哪怕只是为了提高自己下次自己定位的能力!)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using System.Threading;
namespace TANTest.Threading
{
[TestFixture]
public class MetaTaskTests
{
private const int SafeTimeOutMillisecs = 1000;
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_NewTaskCompletes()
{
var task = new Task(() => { });
task.Start();
Thread.Sleep(10);
Assert.That(task.IsCompleted, Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_EmptySetOfTasks_WaitsProceed()
{
var tasks = new List<Task>();
Task.WaitAny(tasks.ToArray());
Task.WaitAll(tasks.ToArray());
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_EmptySetOfTasks_WaitsGiveExpectedOutputs()
{
var tasks = new List<Task>();
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.EqualTo(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfCompletedTasks_WaitsProceed()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.ForEach(task => task.Start());
Thread.Sleep(10);
Task.WaitAny(tasks.ToArray());
Task.WaitAll(tasks.ToArray());
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfCompletedTasks_WaitsGiveExpectedOutputs()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.ForEach(task => task.Start());
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.GreaterThan(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.True);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfUnstartedTasks_WaitsDontProceed()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.EqualTo(-1));
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.False);
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfTasksWithOneCompleted_AnyProceedsAndOutputsIndex()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.First().Start();
Thread.Sleep(10);
Assert.That(Task.WaitAny(tasks.ToArray()), Is.GreaterThan(-1));
}
[Test, Timeout(SafeTimeOutMillisecs)]
public void Meta_SetOfTasksWithOneCompleted_AllTimesOutWithExpectedOutput()
{
var tasks = new List<Task>
{
new Task(() => { }),
new Task(() => { })
};
tasks.First().Start();
Thread.Sleep(10);
Assert.That(Task.WaitAll(tasks.ToArray(), TimeSpan.FromMilliseconds(100)), Is.False);
}
}
}