【发布时间】:2017-05-23 01:43:21
【问题描述】:
我一直在用 C# 中的 TPL 进行一些测试,以更好地了解线程是如何创建的以及何时启动新线程。
在下面的测试中,第一个不使用async/await 的测试行为符合预期,并且总是返回我期望的值。但是,使用async/await 的最后 2 次测试非常不一致。
在我的测试中,我做了以下假设:
-
由于任务已完成,
GetThreadIdInstant将返回同一线程。 -
GetThreadIdDelayed将在不同的线程上返回,因为延迟不会立即返回。 -
由于使用了
Task.Run(),GetThreadIdForcedNew将在不同的线程上返回。
有没有解释为什么上述假设在任务上使用.Result 时是正确的,但在使用async/await 时却不一致?
编辑:澄清“不一致”测试:所以最后 2 个测试使用 async/await,我仍然希望它们给出与使用 .Result 的第一个测试相同的结果,这是不正确的。但是,我在for 循环中包含代码的原因是某些迭代有效,然后我的Assert 语句将失败。我使用“不一致”这个词的原因是 b/c 不断地运行测试,并且在只运行它们与调试它们之间交替导致它们有时通过有时失败。
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Parallels.Tests
{
[TestClass]
public class GetterTests
{
//this test always succeeds
[TestMethod]
public void ResultTest()
{
for (var i = 0; i < 500; i++)
{
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
var instantThreadId = ThreadGetter.GetThreadIdInstant().Result;
var delayedThreadId = ThreadGetter.GetThreadIdDelayed().Result;
var forcedNewThreadId = ThreadGetter.GetThreadIdForcedNew().Result;
Assert.AreEqual(currentThreadId, instantThreadId);
Assert.AreNotEqual(currentThreadId, delayedThreadId);
Assert.AreNotEqual(currentThreadId, forcedNewThreadId);
}
}
//mixed results
[TestMethod]
public async Task AwaitDelayedTest()
{
for (var i = 0; i < 500; i++)
{
try
{
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
var delayedThreadId = await ThreadGetter.GetThreadIdDelayed();
Assert.AreNotEqual(currentThreadId, delayedThreadId);
}
catch (Exception ex)
{
throw new Exception($"failed at iteration: {i}", ex);
}
}
}
//mixed results
[TestMethod]
public async Task AwaitForcedNewTest()
{
for (var i = 0; i < 500; i++)
{
try
{
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
var forcedNewThreadId = await ThreadGetter.GetThreadIdForcedNew();
Assert.AreNotEqual(currentThreadId, forcedNewThreadId);
}
catch (Exception ex)
{
throw new Exception($"failed at iteration: {i}", ex);
}
}
}
}
public static class ThreadGetter
{
public static async Task<int> GetThreadIdInstant() => Thread.CurrentThread.ManagedThreadId;
public static async Task<int> GetThreadIdDelayed()
{
await Task.Delay(1);
return Thread.CurrentThread.ManagedThreadId;
}
public static async Task<int> GetThreadIdForcedNew() => await Task.Run(() => Thread.CurrentThread.ManagedThreadId);
}
}
【问题讨论】:
-
如果您能准确解释“非常不一致”的含义,那将非常有帮助。如果不知道结果是什么,就很难解释结果。
-
我试图进一步澄清我所说的“不一致”的含义。
标签: c# multithreading asynchronous async-await task-parallel-library