C# 中 Task

1. Task,它代表了一个异步操作的执行和完成。可以用来封装一个异步操作,使其可以在不阻塞主线程的情况下执行,并在操作完成后获取结果。

   

复制代码
 1         static void Main(string[] args)
 2         {
 3             MyFun();
 4             Console.Read();
 5         }
 6         static void MyFun()
 7         {
 8            // var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
 9             Task t1 = new Task<int>(()=>MyMethod("write"));
10             Task t2 = Task<int>.Factory.StartNew(() => MyMethod("red"));//这个会自动开始
11             t1.Start();//这个必须手动开始
12         }
13         static int MyMethod(string name)
14         {
15             Console.WriteLine($"I am {name}");
16             return 0;
17         }
复制代码

 

2. 示例:UseMethodAsync()通过Task.Run 将该操作提交给线程池,并使用 await 等待其完成获取到结果。

复制代码
static async Task<int> LongOperationAsync()
{    
    // 模拟耗时操作    
    await Task.Delay(1000);    
    return 42; // 假设这是耗时操作的返回结果
}

static async Task UseMethodAsync()
{    
    int result = await Task.Run(() => LongOperationAsync());    
    Console.WriteLine($"操作结果: {result}");
}
复制代码

3. 使用Task处理并行任务,并等待全部完成后获取结果(多个Task任务完成,新的任务才会完成)

复制代码
static async Task ParallelProcessingAsync()
{    
    Task<int> task1 = Task.Run(() => LongOperationAsync());    
    Task<int> task2 = Task.Run(() => LongOperationAsync());    
    Task<int> task3 = Task.Run(() => LongOperationAsync());
    // 等待所有任务完成    
    await Task.WhenAll(task1, task2, task3);
    // 可以继续处理任务结果    
    Console.WriteLine("所有任务已完成");
}
复制代码

4. Task中的取消

复制代码
static async Task<int> LongOperationWithCancellationAsync(CancellationToken cancellationToken)
{    
    await Task.Delay(1000, cancellationToken);    
    return 42;
}
static async Task MyMethodWithCancellationAsync()
{    
    using (var cts = new CancellationTokenSource())    
    {        
        Task<int> task = Task.Run(() => LongOperationWithCancellationAsync(cts.Token));                
        // 模拟超时逻辑,实际使用时可能基于其他条件        
        cts.CancelAfter(1000); // 1000毫秒(1秒)后取消任务
        try        
       {           
             int result = await task; 
             Console.WriteLine($"操作结果: {result}");        
       }        
       catch (OperationCanceledException)        
       {            
             Console.WriteLine("操作已被取消");        
       }    
    }
}
复制代码

5.  Task中的错误处理

复制代码
static async Task<int> OperationWithFailAsync()
{   
     // 模拟可能失败的操作    
    await Task.Delay(100);    
    throw new InvalidOperationException("操作失败");
}

static async Task HandleTaskAsync()
{   
    try   
   {       
       await Task.Run(() => OperationWithFailAsync());    
   }    
   catch (Exception ex)   
   {        
       Console.WriteLine($"发生错误: {ex.Message}");    
   }
}
复制代码

 6.  Task中的继续处理Task.ContinueWith:可以指定在任务完成之后,应开始运行之后另一个特定任务

    a. ContinueWith()会等待,直到firstTask运行状态达到 IsCompleted,因为TaskContinuationOptions中用的是OnlyOnRanToCompletion

复制代码
 1         static int TaskMethod(string name, int seconds)
 2         {
 3             Console.WriteLine("Task {0} is running.thread id {1},Is thread pool:{2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
 4             Thread.Sleep(TimeSpan.FromSeconds(seconds));
 5             return 60 * seconds;
 6         }
 7         static void Main(string[] args)
 8         {
 9             var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
10             firstTask.ContinueWith(t=>Console.WriteLine("First Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),TaskContinuationOptions.OnlyOnRanToCompletion);
11             firstTask.Start();
12 
13             //主线程工作
14             Console.WriteLine("Back Work:thread id {0},Is thread pool:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
15             Console.Read();
16         }

注意:不会影响主线程。

 

复制代码

    b. 

复制代码
 1  static int TaskMethod(string name, int seconds)
 2         {
 3             Console.WriteLine("Task {0} is running.thread id {1},Is thread pool:{2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
 4             Thread.Sleep(TimeSpan.FromSeconds(seconds));
 5             return 60 * seconds;
 6         }
 7         static void Main(string[] args)
 8         {
 9             Console.WriteLine("Main thread id {0},Is thread pool:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
10 
11             var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
12             var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));
13             firstTask.ContinueWith(t=>Console.WriteLine("First Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),TaskContinuationOptions.OnlyOnRanToCompletion);
14             
15             
16             firstTask.Start();
17             secondTask.Start();
18 
19            // Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。
20             secondTask.ContinueWith(t => Console.WriteLine("Second Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread), TaskContinuationOptions.OnlyOnRanToCompletion|TaskContinuationOptions.ExecuteSynchronously );
21 
22 
23             //主线程工作
24             Console.Read();
25         }

注释调此句: //Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。
由于主线程很早就结束了,因此secondTask只能接受到OnlyOnRanToCompletion,因此还是运行在线程池中。

 

不注释调此句: Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。
这里主线程休眠了足足4秒钟,足以让firstTask和secondTask两个任务完成运行,而后,由于secondTask的后续除了接受OnlyOnRanToCompletion外,还接受ExecuteSynchronously。
因此,后续运行中,由于主线程还没有结束,因此 ExecuteSynchronously得到认可,故secondTask的后续是在主线程上运行,不是在线程池。

 

复制代码

7. Task的Task.WhenAny,WhenAll

复制代码
static async Task<string> DoMethod(int time,string name="wo")
{
Console.WriteLine($"{name} come in.");
await Task.Delay(TimeSpan.FromMilliseconds(time));
return string.Format("{0} have done this work,time is {1}", name, time);
}

static async Task TimeOutMethod(int needTimeOut)
        {
            Console.WriteLine($"needTimeOut={needTimeOut}");
            var t = new Stopwatch();
            t.Start();// 开始计时
            var timeOutTask = Task.Run(() => Task.Delay(150).ContinueWith(_ => "Task timeOutTask finished after 150 seconds")); ;//创建超时任务。
            var doing = DoMethod(needTimeOut);//需要执行的任务。       
            var task = await Task.WhenAny(timeOutTask, doing);//两个任务,只要有一个完成,就返回
            Console.WriteLine(task.Result);   
            t.Stop();
            Console.WriteLine("used time:" + t.Elapsed.TotalMilliseconds);
           

        }

 static void Main(string[] args)
        {
            TimeOutMethod(50);
            TimeOutMethod(500);
            Console.Read();
        }

说明:
传50做参数的时候,
DoMethod先完成,所以返回:wo have done this work,time is 50
传500做参数的时候,timeOutTask先完成,返回:Task timeOutTask finished after 150 seconds

 

 
复制代码

 

复制代码
 /// <summary>
        /// 多任务一起执行,并获取结果,及处理
        /// </summary>
        /// <returns></returns>
        static async Task Tasks()
        {
            var t = new Stopwatch();
            t.Start();// 开始计时
            var list = new List<string>();
            var t1 = DoMethod(1000, "1000");
            var t2 = DoMethod(1500, "1500");
            var t3 = DoMethod(1200, "1200");
            var tasks = new[] { t1, t2, t3 };

            //收集返回值
            var process = tasks.Select(async tt =>
              {
                  var result = await tt;
                  list.Add(result);
              });
            //等待所有任务完成,才有返回值
            await Task.WhenAll(process);
            foreach(var i in list)
            {
                Console.WriteLine(i);
            }
            t.Stop();
            Console.WriteLine("used time:" + t.Elapsed.TotalMilliseconds);
        }

 static void Main(string[] args)
        {
            Tasks();
            Console.Read();
        }
等到所有任务都完成(时间短的还是先完成)

 

 
复制代码

 

posted @   apple-hu  阅读(1206)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示