如何在循环中异步执行 运行 任务?
How do I asynchronously run tasks in a loop?
我有一个 .NET 3.1 Core 应用程序。我正在学习使用任务并行库。为此,我想创建一个基本的 Task
。我想通过扩展方法 运行 这个 Task
。此时,我有以下内容:
var tasks = new List<Task<int>>(); // Used to track the calculated result
var details = new List<Details>(); // Used for debugging purposes
var random = new Random(); // Used to generate a random wait time
var offset = 10; // This value is used to perform a basic calculation
// The following tasks should run the tasks OUT OF ORDER (i.e. 4, 5, 2, 3, 1)
var stopwatch = Stopwatch.StartNew(); // Keep track of how long all five calculations take
for (var i=1; i<=5; i++)
{
var shouldBe = i + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = i + offset;
Console.WriteLine($"{i} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>());
details.Add(d);
}
stopwatch.Stop();
Task.WaitAll(tasks.ToArray());
foreach (var t in tasks)
{
Console.WriteLine($"Result: {t.Result}");
}
// Calculate how long the whole thing took
var totalMilliseconds = 0.0;
foreach (var log in logs)
{
totalMilliseconds = totalMilliseconds + log.TotalMilliseconds;
}
Console.WriteLine($"Runtime: {stopwatch.Elapsed.TotalMilliseconds}, Execution: {totalMilliseconds}");
MyExtensions.cs
namespace System.Threading.Tasks
{
public static class MyExtensions
{
public static async Task<T> ExecuteAsync<T>(this Task<T> code, Details details)
{
T result = default(T);
Stopwatch stopwatch = Stopwatch.StartNew();
code.Start();
await code.ConfigureAwait(false);
result = code.Result;
stopwatch.Stop();
return result;
}
}
// The following class is only for debugging purposes
public class Details
{
public int SleepTime { get; set; }
public double TotalMilliseconds { get; set; }
}
}
当我 运行 这个应用程序时,我在终端 window 中看到如下内容:
6 + 10 = 16 (over 44 ms.)
6 + 10 = 16 (over 197 ms.)
6 + 10 = 16 (over 309 ms.)
6 + 10 = 16 (over 687 ms.)
6 + 10 = 16 (over 950 ms.)
Result: 16
Result: 16
Result: 16
Result: 16
Result: 16
Runtime: 3.5835, Execution: 2204.62970000004
根据此输出,似乎我有五个异步任务 运行ning。睡眠时间每次都会改变(这很好)。 运行 时间小于执行时间,这意味着任务 运行 是并行的。但是,这几乎就像任务在 'for' 循环完成后得到 运行 。这是我唯一能看到 6
来源的地方。但是,我不明白为什么,或者如何解决它。结果应该更像:
4 + 10 = 14
5 + 10 = 15
2 + 10 = 12
3 + 10 = 13
1 + 10 = 11
我做错了什么?为什么每次都使用相同的 i
值?我该如何解决这个问题?
非常感谢您的帮助!
i 的值不是函数的局部值,也就是 mem 分配是相同的,所以它发生了变化。
for (var i=1; i<=5; i++)
{
var shouldBe = i + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = i + offset;
Console.WriteLine($"{i} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>());
details.Add(d);
}
这应该可以正确打印
for (var i=1; i<=5; i++)
{
var localCounter = i;
var shouldBe = localCounter + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = localCounter + offset;
Console.WriteLine($"{localCounter} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>()); //<- this extention method is just making it more completcated to read. i would remove it.
details.Add(d);
}
这应该有助于一个桶
static async Task Main(string[] args)
{
var random = new Random();
List<Task<Details>> tasks = new List<Task<Details>>();
for (var i = 1; i <= 20; i++)
{
var localCounter = i;
var t = new Task<Details>(() => {
var ms = random.Next(1001);
Task.Delay(ms);
var result = new Details
{
Id = localCounter,
DelayTime = ms
};
Console.WriteLine($"basically done id: {localCounter}");
return result;
});
tasks.Add(t);
}
tasks.ForEach(t => t.Start());
Task.WaitAll(tasks.ToArray());
foreach (var item in tasks)
{
Console.WriteLine($"id: {item.Result.Id}");
Console.WriteLine($"random delay: {item.Result.DelayTime}");
}
}
我有一个 .NET 3.1 Core 应用程序。我正在学习使用任务并行库。为此,我想创建一个基本的 Task
。我想通过扩展方法 运行 这个 Task
。此时,我有以下内容:
var tasks = new List<Task<int>>(); // Used to track the calculated result
var details = new List<Details>(); // Used for debugging purposes
var random = new Random(); // Used to generate a random wait time
var offset = 10; // This value is used to perform a basic calculation
// The following tasks should run the tasks OUT OF ORDER (i.e. 4, 5, 2, 3, 1)
var stopwatch = Stopwatch.StartNew(); // Keep track of how long all five calculations take
for (var i=1; i<=5; i++)
{
var shouldBe = i + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = i + offset;
Console.WriteLine($"{i} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>());
details.Add(d);
}
stopwatch.Stop();
Task.WaitAll(tasks.ToArray());
foreach (var t in tasks)
{
Console.WriteLine($"Result: {t.Result}");
}
// Calculate how long the whole thing took
var totalMilliseconds = 0.0;
foreach (var log in logs)
{
totalMilliseconds = totalMilliseconds + log.TotalMilliseconds;
}
Console.WriteLine($"Runtime: {stopwatch.Elapsed.TotalMilliseconds}, Execution: {totalMilliseconds}");
MyExtensions.cs
namespace System.Threading.Tasks
{
public static class MyExtensions
{
public static async Task<T> ExecuteAsync<T>(this Task<T> code, Details details)
{
T result = default(T);
Stopwatch stopwatch = Stopwatch.StartNew();
code.Start();
await code.ConfigureAwait(false);
result = code.Result;
stopwatch.Stop();
return result;
}
}
// The following class is only for debugging purposes
public class Details
{
public int SleepTime { get; set; }
public double TotalMilliseconds { get; set; }
}
}
当我 运行 这个应用程序时,我在终端 window 中看到如下内容:
6 + 10 = 16 (over 44 ms.)
6 + 10 = 16 (over 197 ms.)
6 + 10 = 16 (over 309 ms.)
6 + 10 = 16 (over 687 ms.)
6 + 10 = 16 (over 950 ms.)
Result: 16
Result: 16
Result: 16
Result: 16
Result: 16
Runtime: 3.5835, Execution: 2204.62970000004
根据此输出,似乎我有五个异步任务 运行ning。睡眠时间每次都会改变(这很好)。 运行 时间小于执行时间,这意味着任务 运行 是并行的。但是,这几乎就像任务在 'for' 循环完成后得到 运行 。这是我唯一能看到 6
来源的地方。但是,我不明白为什么,或者如何解决它。结果应该更像:
4 + 10 = 14
5 + 10 = 15
2 + 10 = 12
3 + 10 = 13
1 + 10 = 11
我做错了什么?为什么每次都使用相同的 i
值?我该如何解决这个问题?
非常感谢您的帮助!
i 的值不是函数的局部值,也就是 mem 分配是相同的,所以它发生了变化。
for (var i=1; i<=5; i++)
{
var shouldBe = i + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = i + offset;
Console.WriteLine($"{i} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>());
details.Add(d);
}
这应该可以正确打印
for (var i=1; i<=5; i++)
{
var localCounter = i;
var shouldBe = localCounter + offset;
var d = new Details();
var t = new Task<int>(() => {
var ms = random.Next(1001); // Choose a wait time between 0 and 1 seconds
Thread.Sleep(ms);
d.SleepTime = ms;
var result = localCounter + offset;
Console.WriteLine($"{localCounter} + {offset} = {result} (over {timeout} ms.)");
return result;
});
tasks.Add(t.ExecuteAsync<int>()); //<- this extention method is just making it more completcated to read. i would remove it.
details.Add(d);
}
这应该有助于一个桶
static async Task Main(string[] args)
{
var random = new Random();
List<Task<Details>> tasks = new List<Task<Details>>();
for (var i = 1; i <= 20; i++)
{
var localCounter = i;
var t = new Task<Details>(() => {
var ms = random.Next(1001);
Task.Delay(ms);
var result = new Details
{
Id = localCounter,
DelayTime = ms
};
Console.WriteLine($"basically done id: {localCounter}");
return result;
});
tasks.Add(t);
}
tasks.ForEach(t => t.Start());
Task.WaitAll(tasks.ToArray());
foreach (var item in tasks)
{
Console.WriteLine($"id: {item.Result.Id}");
Console.WriteLine($"random delay: {item.Result.DelayTime}");
}
}