Task启动,暂停,继续,结束

延时:

async Task DelayMethod()
{
    Console.WriteLine("Before Delay");
    await Task.Delay(1000); // 延时1秒
    Console.WriteLine("After Delay");
}

构造方法: 

在C#中,可以使用Task类来创建和管理多线程任务。以下是Task的启动、暂停、继续和结束的方法:

启动Task:
1. 使用Task.Run()方法启动一个新的Task。
2. 使用Task.Factory.StartNew()方法启动一个新的Task。
3. 使用Task构造函数创建一个新的Task,然后调用Task.Start()方法启动它。

暂停Task:
1. 使用ManualResetEvent类创建一个事件对象,然后在Task中使用WaitOne()方法暂停Task。
2. 使用CancellationTokenSource类创建一个取消令牌对象,然后在Task中使用该对象的Cancel()方法暂停Task。

继续Task:
1. 使用ManualResetEvent类的Set()方法继续Task。
2. 使用CancellationTokenSource类的Cancel()方法取消暂停Task。

结束Task:
1. 使用Task.Wait()方法等待Task完成。
2. 使用Task.WaitAll()方法等待多个Task完成。
3. 使用Task.WaitAny()方法等待任何一个Task完成。
4. 使用Task的CancellationTokenSource对象的Cancel()方法取消Task。

public Task(Action action);
public Task(Action action, CancellationToken 取消令牌);
public Task(Action action, TaskCreationOptions 创建选项);
public Task(Action<object> action, object 状态);
public Task(Action action, CancellationToken 取消令牌, TaskCreationOptions 创建选项);
public Task(Action<object> action, object 状态, CancellationToken 取消令牌);
public Task(Action<object> action, object 状态, TaskCreationOptions 创建选项);
public Task(Action<object> action, object 状态, CancellationToken 取消令牌, TaskCreationOptions 创建选项);

public static Task Run(Func<Task> function, CancellationToken cancellationToken关闭线程)
// ctrl+F查找,3312行

第二参数:用于关闭线程。(字段位置)

//CancellationToken   ct = new CancellationToken();
private CancellationTokenSource cts ;//关闭线程用(包含ct)
private ManualResetEvent resetEvent = new ManualResetEvent(true);// 暂停业务

 public static async Task Main()
   {
      var tokenSource = new CancellationTokenSource();// 令牌对象
      var token = tokenSource.Token;// 开关绑定
      var files = new List<Tuple<string, string, long, DateTime>>();

      var t = Task.Run( () => { string dir = "C:\\Windows\\System32\\";
                                object obj = new Object();
                                if (Directory.Exists(dir)) {
                                   Parallel.ForEach(Directory.GetFiles(dir),
                                   f => {
                                           if (token.IsCancellationRequested)
                                              token.ThrowIfCancellationRequested();
                                           var fi = new FileInfo(f);
                                           lock(obj) {
                                              files.Add(Tuple.Create(fi.Name, fi.DirectoryName, fi.Length, fi.LastWriteTimeUtc));          
                                           }
                                      });
                                 }
                              }
                        , token);// 开关绑定
      await Task.Yield();
      tokenSource.Cancel();// 令牌对象

【1】新建线程

cts = new CancellationTokenSource();//关闭线程用
Task task1 = new Task(() =>
            {
                //在这个地方编写我们需要的逻辑...
            }, cts.Token);
task1.Start();// 这句才开启


 Task.Factory.StartNew(() => {
                              canopen.set_reg32bit(Convert.ToInt16(textBox1.Text, 16), 0, Convert.ToInt32(textBox6.Text, 16));
                             });
 Task.Run(() =>
            {
                //这里填业务。。。。。
               i= canopen.get_region(Convert.ToInt16(textBox3.Text, 16), Convert.ToByte(textBox4.Text, 16));

                this.Invoke(new Action(() =>
                {
                    //这里填窗体业务。。。。。

                    textBox5.Text = i.ToString("X8");
                }));
            }
            );


Task.Factory.StartNew(() =>
            {
                canopen.set_reg32bit(0x1017, 0x00, 7000);

            }   );
Task<int> task = Task.Run(() =>
{
    // 这里是需要执行的代码
    return 42;
});

// 这里可以执行一些其他的代码

int result = task.Result; // 这里会阻塞当前线程,直到任务完成并返回结果
Console.WriteLine(result); // 输出 42

//启动线程
        private void btnStart_Click(object sender, EventArgs e)
        {
            cts = new CancellationTokenSource();// 令牌
            CancellationToken ct = cts.Token; //获取令牌

            Task task = new Task(async () =>
            {
                while (true)
                {
                    if (!cts.IsCancellationRequested)
                    {
                        resetEvent.WaitOne();

                        //在下面编写你要让线程完成的任务...
                        Console.WriteLine("任务执行中...");
                        await Task.Delay(1000);
                    }
                    else
                    {
                        return;// 结束线程
                    }
                }
            }, ct);
            task.Start();

            //cts.Cancel();// 结束线程
        }
//暂停   resetEvent.Reset();
//继续   resetEvent.Set();
//结束   cts.Cancel();

令牌结束,没有作用,实际还是要方法体内判断状态,如果是结束,退出方法体,线程才真正结束。 cts.Cancel();只是将只读属性True,方法体内return才真正结束线程。

 Task task3 = Task.Factory.StartNew(() =>
            {
                //在这个地方编写我们需要的逻辑...
            });

【2】排队等待:

     Task task1 = new Task(() =>
             {
                 Thread.Sleep(1000);
                 Console.WriteLine($"Task1子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
             });
            task1.Start();
            Task task2 = new Task(() =>
            {
                Thread.Sleep(2000);
                Console.WriteLine($"Task2子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
            });
            task2.Start();

            //第1种方式:挨个等待和前面一样
            //task1.Wait();
            //task2.Wait();

            //第2种方式:等待所有的任务完成    【推荐】
            //Task.WaitAll(task1, task2);

            //第3种方式:等待任何一个完成即可  【推荐】
            Task.WaitAny(task1, task2);

            Console.WriteLine("主线程开始运行!Time=" + DateTime.Now.ToLongTimeString());
//线程的延续(主线程不等待,子线程依次执行,如果你需要主线程也按照子线程的顺序来,请你自己把主线程的任务放到延续任务中就可以)
            Task.WhenAll(task1, task2).ContinueWith(task3 =>
             {
                 //在这里可以编写你需要的业务...

                 Console.WriteLine($"Task3子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
             });

            Console.WriteLine("主线程开始运行!Time=" + DateTime.Now.ToLongTimeString());

12都完成3才run

//线程的延续(主线程不等待,子线程任何一个执行完毕,就会执行后面的线程)
            Task.WhenAny(task1, task2).ContinueWith(task3 =>
            {
                //在这里可以编写你需要的业务...

                Console.WriteLine($"Task3子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
            });

有1个完成,3就run 

Task parentTask = new Task(() =>
             {
                 Task task1 = new Task(() =>
                  {
                      Thread.Sleep(1000);
                  }, TaskCreationOptions.AttachedToParent);

                 Task task2 = new Task(() =>
                 {
                     Thread.Sleep(3000);
                 }, TaskCreationOptions.AttachedToParent);
                 task1.Start();
                 task2.Start();
             });

            parentTask.Start();
            parentTask.Wait();//等待附加的子任务全部完成。相当于Task.WaitAll(taks1,task2);
            //TaskCreationOptions.AttachedToParent如果这个枚举参数不添加,主线程会直接运行,不等待
            Console.WriteLine("主线程开始执行!Time=  " + DateTime.Now.ToLongTimeString());

耗时线程: 

//长时间的任务运行,需要采取的方法
            Task task1 = new Task(() =>
            {
                Thread.Sleep(2000);
               
            }, TaskCreationOptions.LongRunning);

            //LongRunning:如果你明确知道这个任务是长时间运行的,建议你加上。当然你使用Thread也是可以的。但是不要使用
            //ThreadPool,因为长时间占用不归还线程,系统会强制开启新的线程,会一定程度影响性能
            task1.Start();
            task1.Wait();

            Console.WriteLine("主线程开始执行!Time=  " + DateTime.Now.ToLongTimeString());
        

【3】线程取消

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Run(() =>
        {
            // Were we already canceled?
            ct.ThrowIfCancellationRequested();

            bool moreToDo = true;
            while (moreToDo)
            {
                // Poll on this property if you have to do
                // other cleanup before throwing.
                if (ct.IsCancellationRequested)
                {
                    // Clean up here, then...
                    ct.ThrowIfCancellationRequested();
                }
            }
        }, tokenSource2.Token); // Pass same token to Task.Run.

        tokenSource2.Cancel();

        // Just continue on this thread, or await with try-catch:
        try
        {
            await task;
        }
        catch (OperationCanceledException e)
        {
            Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
        }
        finally
        {
            tokenSource2.Dispose();
        }

        Console.ReadKey();
    }
}

// https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/task-cancellation

 任务取消 | Microsoft Learn

//创建取消信号源对象
            CancellationTokenSource cts = new CancellationTokenSource();

            Task task = Task.Factory.StartNew(() =>
              {
                  while (!cts.IsCancellationRequested)//判断任务是否被取消
                  {
                      Thread.Sleep(200);

                      Console.WriteLine($"子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
                  }
              }, cts.Token);

            //我们在这个地方模拟一个事件产生
            Thread.Sleep(2000);
            cts.Cancel();//取消任务,只要传递这样一个信号就可以
 CancellationTokenSource cts = new CancellationTokenSource();
            Task task = Task.Factory.StartNew(() =>
            {
                while (!cts.IsCancellationRequested)
                {
                    Thread.Sleep(500);

                    Console.WriteLine($"子线程Id={Thread.CurrentThread.ManagedThreadId}  {DateTime.Now.ToLongTimeString()}");
                }
            }, cts.Token);

            //注册一个委托:这个委托将在任务取消的时候调用
            cts.Token.Register(() =>
            {
                //在这个地方可以编写自己要处理的逻辑...
                Console.WriteLine("任务取消,开始清理工作......");
                Thread.Sleep(2000);
                Console.WriteLine("任务取消,清理工作结束......");
            });

            //这个地方肯定是有其他的逻辑来控制取消
            Thread.Sleep(3000);//模拟其他的耗时工作
            cts.Cancel();//取消任务

限时任务: 

cts.CancelAfter(3000); //3秒后自动取消

重新开的线程,需要用新的cts绑定。

Lock锁:锁对象,必须是引用类型

 //为什么要用锁?在多线程中,尤其是静态资源的访问,必然会有竞争

        private static int nums = 0;
        private static object myLock = new object();// 必须引用类型
        static void Method12()
        {
            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    TestMethod();
                });
            }
        }

        static void TestMethod()
        {
            for (int i = 0; i < 100; i++)
            {
                lock (myLock)// 锁住引用类型
                {
                    nums++;
                    Console.WriteLine(nums);
                }
            }
        }
        //Lock是Monitor语法糖,本质是解决资源的锁定问题
        //我们锁住的资源一定是让线程可访问到的,所以不能是局部变量。
        //锁住的资源千万不要是值类型。
        //lock也不能锁住string类型。

lock内,对象是同一个,才能进入

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Define the cancellation token.
      CancellationTokenSource source = new CancellationTokenSource();
      CancellationToken token = source.Token;

      Random rnd = new Random();
      Object lockObj = new Object();
      
      List<Task<int[]>> tasks = new List<Task<int[]>>();
      TaskFactory factory = new TaskFactory(token);
      for (int taskCtr = 0; taskCtr <= 10; taskCtr++) {
         int iteration = taskCtr + 1;
         tasks.Add(factory.StartNew( () => {
           int value;
           int[] values = new int[10];
           for (int ctr = 1; ctr <= 10; ctr++) {
              lock (lockObj) {
                 value = rnd.Next(0,101);
              }
              if (value == 0) { 
                 source.Cancel();
                 Console.WriteLine("Cancelling at task {0}", iteration);
                 break;
              }   
              values[ctr-1] = value; 
           }
           return values;
        }, token));   
      }
      try {
         Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(), 
         (results) => {
            Console.WriteLine("Calculating overall mean...");
            long sum = 0;
            int n = 0; 
            foreach (var t in results) {
               foreach (var r in t.Result) {
                  sum += r;
                  n++;
               }
            }
            return sum/(double) n;
         } , token);
         Console.WriteLine("The mean is {0}.", fTask.Result);
      }   
      catch (AggregateException ae) {
         foreach (Exception e in ae.InnerExceptions) {
            if (e is TaskCanceledException)
               Console.WriteLine("Unable to compute mean: {0}", 
                  ((TaskCanceledException) e).Message);
            else
               Console.WriteLine("Exception: " + e.GetType().Name);
         }
      }
      finally {
         source.Dispose();
      }
   }
}
// Repeated execution of the example produces output like the following:
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 10
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 5.29545454545455.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 6
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 4.97363636363636.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 5
//       Unable to compute mean: A task was canceled.
//       
//       Cancelling at task 4
//       Unable to compute mean: A task was canceled.
//       
//       Calculating overall mean...
//       The mean is 4.86545454545455.

  • 6
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
当Visual Studio在运行过程中暂停后,可以进行以下操作来继续执行程序。 1. 检查是否有断点设置:如果程序在暂停时是由于设置了断点而触发的,可以通过点击断点旁边的红色圆圈来取消断点。这样程序将会继续执行直到下一个断点或程序结束。 2. 使用F10或F11键:按下F10键将会逐行执行代码,而按下F11键将会进入函数内部继续执行。这两个键是用于单步调试的常用快捷键,可以帮助你逐步跟踪程序的执行过程。 3. 使用Continue按钮:在Visual Studio的调试工具栏中有一个Continue按钮,点击它将会继续执行程序直到下一个断点或程序结束。 如果你遇到了Visual Studio本身的设置问题导致窗口不显示或一闪而逝的情况,可以尝试以下解决方法: 1. 检查窗口显示设置:在Visual Studio的"工具"菜单下选择"选项",然后在弹出的对话框中选择"环境"->"一般",确保"在运行时自动显示输出窗口"选项被勾选。 2. 检查代码错误:如果程序出现窗口不显示或一闪而逝的情况,可能是代码中存在错误导致程序无法正常执行。可以通过检查代码逻辑和语法错误来解决此问题。 3. 重启Visual Studio:有时候,重新启动Visual Studio可以解决一些临时的显示问题。 希望这些方法能帮助你解决Visual Studio暂停继续执行的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Visual Studio IDE编写程序时不显示窗口或窗口一闪而逝的解决方法](https://download.csdn.net/download/weixin_38592420/14874949)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Visual Studio 2022 更新到一半停止导致的问题](https://blog.csdn.net/qq_41312566/article/details/125892513)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值