编辑代码

using System;

using System.Diagnostics;  
using System.Threading;  
using System.Threading.Tasks;  
  
class Program  
{  
    static async Task Main(string[] args)  
    {  
        // 定义一个取消令牌源  
        using (var cts = new CancellationTokenSource())  
        {  
            // 创建两个任务  
            var task1 = Task.Run(() => CalculatePiSeries1(cts.Token, 3.1415926535898));  
            var task2 = Task.Run(() => CalculatePiSeries2(cts.Token, 3.1415926535898));  
  
            // 等待两个任务中的任何一个完成,并处理结果  
            Task completedTask = await Task.WhenAny(task1, task2);  
  
            // 取消另一个任务(如果它还在运行)  
            cts.Cancel();  
  
            // 检查哪个任务完成了,并输出结果  
            if (completedTask == task1)  
            {  
                var result1 = await task1;  
                Console.WriteLine("Series 1 completed faster with result: " + result1);  
            }  
            else if (completedTask == task2)  
            {  
                var result2 = await task2;  
                Console.WriteLine("Series 2 completed faster with result: " + result2);  
            }  
  
            // 处理可能存在的未捕获的异常(如果有的话)  
            try  
            {  
                await Task.WhenAll(task1, task2);  
            }  
            catch (OperationCanceledException) { } // 忽略取消异常  
        }  
  
        Console.ReadLine(); // 防止控制台窗口立即关闭  
    }  
  
    static async Task<(double result, Stopwatch sw)> CalculatePiSeries1(CancellationToken token, double targetPi)  
    {  
        Stopwatch sw = Stopwatch.StartNew();  
        double pi = 0;  
        double term = 1;  
        int i = 0;  
  
        while (true)  
        {  
            if (token.IsCancellationRequested) break; // 检查是否取消  
  
            if (i % 2 == 0)  
            {  
                pi += term;  
            }  
            else  
            {  
                pi -= term;  
            }  
  
            term = 1.0 / (2 * i + 1);  
            i++;  
  
            // 检查是否达到精度要求  
            if (Math.Abs(pi * 4 - targetPi) < Math.Pow(10, -10))  
            {  
                sw.Stop();  
                return (pi * 4, sw);  
            }  
        }  
  
        sw.Stop();  
        return (pi * 4, sw); // 如果被取消,也返回结果和计时器  
    }  
  
    static async Task<(double result, Stopwatch sw)> CalculatePiSeries2(CancellationToken token, double targetPi)  
    {  
        Stopwatch sw = Stopwatch.StartNew();  
        double piSquared = 0;  
        int i = 0;  
  
        while (true)  
        {  
            if (token.IsCancellationRequested) break; // 检查是否取消  
  
            piSquared += 1.0 / Math.Pow(2 * i + 1, 2);  
            i++;  
  
            // 检查是否达到精度要求(注意这里我们比较的是平方)  
            double pi = Math.Sqrt(8*piSquared);  
            if (Math.Abs(pi * pi - targetPi*targetPi) < Math.Pow(10, -10))  
            {  
                sw.Stop();  
                return (pi, sw);  
            }  
        }  
  
        sw.Stop();  
        return (Math.Sqrt(8*piSquared), sw); // 如果被取消,也返回结果和计时器  
    }  
}