面试题答案
一键面试- 使用TPL创建并启动并行任务计算整数平方和:
- 以下是使用
Parallel.For
方法并行计算一组整数平方和的示例代码:
- 以下是使用
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
long sum = 0;
Parallel.For(0, numbers.Length, i =>
{
checked
{
long square = (long)numbers[i] * numbers[i];
lock (typeof(Program))
{
sum += square;
}
}
});
Console.WriteLine($"平方和为: {sum}");
}
}
- 在上述代码中:
- 定义了一个整数数组
numbers
。 - 使用
Parallel.For
方法来并行迭代数组的索引。在Parallel.For
的委托中,计算每个数的平方,并将其累加到sum
变量中。由于sum
是共享变量,为了避免竞态条件,使用lock
关键字来确保线程安全的累加操作。checked
关键字用于检测可能的算术溢出。
- 定义了一个整数数组
- 处理任务可能抛出的异常:
- 使用
Parallel.For
时,如果在循环体中抛出异常,Parallel.For
会捕获这些异常并将它们包装在AggregateException
中。可以使用try - catch
块来捕获并处理这些异常,如下所示:
- 使用
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
long sum = 0;
try
{
Parallel.For(0, numbers.Length, i =>
{
checked
{
long square = (long)numbers[i] * numbers[i];
lock (typeof(Program))
{
sum += square;
}
}
});
}
catch (AggregateException ae)
{
foreach (var innerException in ae.InnerExceptions)
{
if (innerException is OverflowException)
{
Console.WriteLine("发生算术溢出异常: " + innerException.Message);
}
else
{
Console.WriteLine("其他异常: " + innerException.Message);
}
}
}
Console.WriteLine($"平方和为: {sum}");
}
}
- 在这个修改后的代码中,
try - catch
块捕获Parallel.For
可能抛出的AggregateException
。通过遍历InnerExceptions
属性,可以处理每个内部异常。在示例中,针对OverflowException
进行了特殊处理,当然也可以根据实际情况处理其他类型的异常。
另外,如果使用Task
类创建并行任务,可以如下实现:
- 使用
Task
类创建并启动并行任务计算整数平方和:
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
Task<long>[] tasks = new Task<long>[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
int localI = i;
tasks[i] = Task.Run(() =>
{
checked
{
return (long)numbers[localI] * numbers[localI];
}
});
}
Task.WaitAll(tasks);
long sum = 0;
foreach (var task in tasks)
{
sum += task.Result;
}
Console.WriteLine($"平方和为: {sum}");
}
}
- 在上述代码中:
- 创建了一个
Task<long>
类型的数组tasks
,用于存储每个计算平方的任务。 - 使用
for
循环为数组中的每个元素创建一个新的Task
,每个任务计算对应数字的平方。注意在Task.Run
的委托中,为了避免闭包陷阱,使用了一个局部变量localI
。 - 使用
Task.WaitAll
等待所有任务完成,然后遍历任务数组,累加每个任务的结果得到平方和。
- 创建了一个
- 处理
Task
可能抛出的异常:- 同样使用
try - catch
块来捕获Task
可能抛出的异常,如下所示:
- 同样使用
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
Task<long>[] tasks = new Task<long>[numbers.Length];
try
{
for (int i = 0; i < numbers.Length; i++)
{
int localI = i;
tasks[i] = Task.Run(() =>
{
checked
{
return (long)numbers[localI] * numbers[localI];
}
});
}
Task.WaitAll(tasks);
long sum = 0;
foreach (var task in tasks)
{
sum += task.Result;
}
Console.WriteLine($"平方和为: {sum}");
}
catch (AggregateException ae)
{
foreach (var innerException in ae.InnerExceptions)
{
if (innerException is OverflowException)
{
Console.WriteLine("发生算术溢出异常: " + innerException.Message);
}
else
{
Console.WriteLine("其他异常: " + innerException.Message);
}
}
}
}
}
- 在这个代码中,
try - catch
块捕获Task.WaitAll
可能抛出的AggregateException
,同样通过遍历InnerExceptions
属性来处理每个内部异常。