我有一個名爲WaitForAction的方法,它接受一個Action委託並在新任務中執行它。該方法阻塞,直到任務完成或超時過期。它使用ManualResetEvent等待超時/完成。任務似乎互相阻塞
以下代碼顯示了在多線程環境中測試該方法的嘗試。
class Program
{
public static void Main()
{
List<Foo> list = new List<Foo>();
for (int i = 0; i < 10; i++)
{
Foo foo = new Foo();
list.Add(foo);
foo.Bar();
}
SpinWait.SpinUntil(() => list.Count(f => f.finished || f.failed) == 10, 2000);
Debug.WriteLine(list.Count(f => f.finished));
}
}
public class Foo
{
public volatile bool finished = false;
public volatile bool failed = false;
public void Bar()
{
Task.Factory.StartNew(() =>
{
try
{
WaitForAction(1000,() => { });
finished = true;
}
catch
{
failed = true;
}
});
}
private void WaitForAction(int iMsToWait, Action action)
{
using (ManualResetEvent waitHandle = new ManualResetEvent(false))
{
Task.Factory.StartNew(() =>
{
action();
waitHandle.SafeSet();
});
if (waitHandle.SafeWaitOne(iMsToWait) == false)
{
throw new Exception("Timeout");
}
}
}
}
由於動作是什麼都不做我希望通過調用Foo.Bar 10倍的超時時間內完成好開始了10個任務。有時會發生這種情況,但通常程序需要2秒才能執行並報告只有2個Foo「完成」實例沒有錯誤。換句話說,8個對WaitForAction的調用已經超時。
我假設WaitForAction是線程安全的,因爲任務提供的線程上的每個調用都有自己的堆棧。我通過記錄線程ID和每個調用的等待句柄ID或多或少證明了這一點。
我意識到這個代碼是一個愚蠢的例子,但我對這個原理感興趣。任務調度程序是否有可能將運行該操作委託的任務調度到已在等待另一個操作完成的同一個線程池線程?還是還有其他事情我錯過了?
謝謝。作品。我不知道線程池在按需分配新線程方面速度很慢。 –
@RonIdaho正常的假設是,你將在工作線程上做有用的CPU密集型工作,而不是阻塞它。因此,初始大小對於CPU密集型工作來說通常是最佳的,分配新線程不會提高性能(甚至可能會影響性能)。 –