我有以下代码:
static void Main(string[] args)
{
IEnumerable<int> threadsIds = Enumerable.Range(1, 1000);
DateTime globalStart = DateTime.Now;
Console.WriteLine("{0:s.fff} Starting tasks", globalStart);
Parallel.ForEach(threadsIds, (threadsId) =>
{
DateTime taskStart = DateTime.Now;
const int sleepDuration = 1000;
Console.WriteLine("{1:s.fff} Starting task {0}, sleeping for {2}", threadsId, taskStart, sleepDuration);
Thread.Sleep(sleepDuration);
DateTime taskFinish = DateTime.Now;
Console.WriteLine("{1:s.fff} Ending task {0}, task duration {2}", threadsId, taskFinish, taskFinish- taskStart);
});
DateTime globalFinish= DateTime.Now;
Console.WriteLine("{0:s.fff} Tasks finished. Total duration: {1}", globalFinish, globalFinish-globalStart);
Console.ReadLine();
}
目前,当我运行它时,运行它需要大约60秒。根据我的理解,这是因为.Net不会为每个任务创建一个线程,而是为所有Tasks
创建一些线程,当我执行Thread.Sleep
时,我会阻止此线程执行其他一些任务。
在我的实际情况中,我有一些工作要并行完成,如果失败,我会等待一段时间才能再次尝试。
我正在查找除Thread.Sleep
之外的其他内容,这将允许其他任务在&#34;休眠时间内运行&#34;其他任务。
不幸的是,我目前正在运行.Net 4,这阻止我使用async
和await
(在这种情况下我想这可以帮助我。
Ps,我得到了相同的结果:
Task.Delay(sleepDuration).Wait()
Parallel.Foreach
,而是使用Task.Factory.StartNew
Ps2,我知道我能以不同的方式处理我的真实情况,但我非常乐意了解如何以这种方式实现。
答案 0 :(得分:-1)
你走在正确的道路上。 Task.Delay(timespan)
是解决您问题的方法。由于您无法使用async/await
,因此您必须编写更多代码才能获得所需的结果。
考虑使用Task.ContinueWith()
方法,例如:
Task.Run(() => { /* code before Thread.Sleep */ })
.ContinueWith(task => Task.Delay(sleepDuration)
.ContinueWith(task2 => { /* code after Thread.Sleep */ }));
此外,您还需要创建一个类,以便在子任务中访问本地方法变量。
如果您想创建一个将每秒运行一次轮询的任务,您可以尝试以下代码:
Task PollTask(Func<bool> condition)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
PollTaskImpl(tcs, condition);
return tcs.Task;
}
void PollTaskImpl(TaskCompletionSource<bool> tcs, Func<bool> condition)
{
if (condition())
tcs.SetResult(true);
else
Task.Delay(1000).ContinueWith(_ => PollTaskImpl(tcs, condition));
}
不要担心每秒创建新任务 - ContinueWith
和async/await
方法在内部执行相同的操作。