zoukankan      html  css  js  c++  java
  • 多线程

    目录--作者:hnZheng
    	* 
    线程池以异步的方式执行一个方法
    	* 
    线程执行上下文
    	* 
    在异步线程间取消上下文的流动
    	* 
    协作式取消和超时 取消一个正在执行的线程
    	* 
    System.Threading.Tasks任务的使用
    	* 
    等待任务完成并且获取结果
    	* 
    任务完成时启动新的任务
    	* 
    任务可以启动多个子任务
    	* 
    任务工厂的使用
    	* 
    任务调度器 常用
    	* 
    Paraller的静态For 和ForEach 和 Invoke
    	* 
    执行定时计算限制操作 定时程序
    	* 
    同步上下文任务调度器
    
    
    
    // 线程池 异步执行一个方法
    static void Main(string[] args)
    {
    #region 实例二 线程池以异步的方式执行一个方法
    //实例一 线程池以异步的方式执行一个方法
    Console.WriteLine("程序启动开始...");
    ThreadPool.QueueUserWorkItem(FirstMethod);
    Console.WriteLine("执行其他操作...");
    Thread.Sleep(10000);//其他工作执行10秒
    Console.WriteLine("执行结束...");
    Console.ReadLine();
    #endregion
    }
    // 方法的签名要匹配
    public static void FirstMethod(Object state)
    {
    Thread.Sleep(11000);
    Console.WriteLine("执行完FirstMethod...");
    }
    
    //实例二 线程执行上下文
    static void Main(string[] args)
    {
    #region 实例二 线程执行上下文
    //实例二 线程执行上下文
    // 1、将一些数据放在Main线程的逻辑调用上下文中,以下的线程池中加入三个线程
    CallContext.LogicalSetData("Name", "zhenghaonan");
    ThreadPool.QueueUserWorkItem(state =>
    {
    
    Console.WriteLine("This is FirstMethod Name={0}", CallContext.LogicalGetData("Name"));
    });
    
    //在异步线程间取消上下文的流动
    ExecutionContext.SuppressFlow();
    //这个线程中数据没有被流动下来
    ThreadPool.QueueUserWorkItem(state =>
    {
    Console.WriteLine("This is SecondMethod Name={0}", CallContext.LogicalGetData("Name"));
    });
    // 在异步线程中恢复上下文的流动
    ExecutionContext.RestoreFlow();
    // 数据继续流动
    ThreadPool.QueueUserWorkItem(state =>
    {
    Console.WriteLine("This is ThridMethod Name={0}", CallContext.LogicalGetData("Name"));
    });
    GetContextData();
    Console.ReadLine();
    // 以上实例 执行结果为 只有第二个线程中数据没有,其他的线程数据都有,并且四个线程是异步执行的
    
    #endregion
    }
    public static void GetContextData()
    {
    Console.WriteLine("This is GetContextData Name={0}", CallContext.LogicalGetData("Name"));
    Console.WriteLine("This is GetContextData");
    }
    
    //实例三 协作式取消和超时 取消一个正在执行的线程
    static void Main(string[] args)
    {
    #region 实例三 协作式取消和超时 取消一个正在执行的线程
    
    //实例三 协作式取消和超时 取消一个正在执行的线程
    //创建第一个Token
    CancellationTokenSource cts = new CancellationTokenSource();
    //创建第二个Token
    CancellationTokenSource cts1 = new CancellationTokenSource();
    //创建一个线程1
    ThreadPool.QueueUserWorkItem(o =>
    {
    for (int i = 0; i < 50; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine("线程1---{0}", i);
    //获取Token,判断线程是否被取消
    if (cts.Token.IsCancellationRequested)
    {
    //当线程取消操作是
    Console.WriteLine("线程 1 已经被取消");
    break;
    }
    }
    });
    //创建一个线程2
    ThreadPool.QueueUserWorkItem(o =>
    {
    for (int i = 0; i < 50; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine("线程2--{0}", i);
    //获取Token,判断线程是否被取消
    if (cts1.Token.IsCancellationRequested)
    {
    //当线程取消操作是
    Console.WriteLine("线程 2 已经被取消");
    break;
    }
    }
    });
    
    
    //创建一个Token,关联一个或者多个Token,当cts1取消cts2也会被取消
    //CancellationTokenSource cts2 = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token);
    CancellationTokenSource cts2 = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts.Token);// 关联多个Token,只要有一个取消,cts2就会被取消
    //创建一个线程3
    ThreadPool.QueueUserWorkItem(o =>
    {
    for (int i = 0; i < 50; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine("线程3--{0}", i);
    //获取Token,判断线程是否被取消
    if (cts2.Token.IsCancellationRequested)
    {
    //当线程取消操作是
    Console.WriteLine("线程 3 已经被取消");
    break;
    }
    }
    });
    
    // 这里可以注册一个或者多个方法在线程取消时执行
    //注册的三个方法也是异步执行的
    //以下是线程1的Token,线程1取消时进行时的操作
    cts.Token.Register(() => { Console.WriteLine("线程1取消时进行的操作0"); });
    cts.Token.Register(() => { Console.WriteLine("线程1取消时进行的操作1"); });
    cts.Token.Register(() => { Console.WriteLine("线程1取消时进行的操作2"); });
    
    //以下是线程2的Token,线程1取消时进行时的操作
    cts1.Token.Register(() => { Console.WriteLine("线程2取消时进行的操作0"); });
    cts1.Token.Register(() => { Console.WriteLine("线程2取消时进行的操作1"); });
    cts1.Token.Register(() => { Console.WriteLine("线程2取消时进行的操作2"); });
    
    //以下是线程3的Token,线程1取消时进行时的操作
    cts2.Token.Register(() => { Console.WriteLine("线程3取消时进行的操作0"); });
    cts2.Token.Register(() => { Console.WriteLine("线程3取消时进行的操作1"); });
    cts2.Token.Register(() => { Console.WriteLine("线程3取消时进行的操作2"); });
    
    Console.WriteLine("线程将在10秒后取消");
    //定时取消一个线程的执行,将于10秒后停止执行
    //cts.CancelAfter(10000);
    
    Console.WriteLine("回车取消当前线程");
    Console.ReadLine();
    //立即取消一个线程的执行,取消线程1
    cts.Cancel();
    //立即取消一个线程的执行取消线程2
    cts1.Cancel();
    
    Console.ReadLine();
    //ThreadPool的QueueUserWorkItem的异步操作,有许多限制,最大的问题就是没有内建的机制,你不知道这个线程什么时候完成,
    //也没有操作完成时的返回值,为了克服这些限制,使用System.Threading.Tasks中任务同样可以做异步造作.
    #endregion
    }
    
    //实例四 System.Threading.Tasks任务的使用
    static void Main(string[] args)
    {
    #region System.Threading.Tasks任务的使用
    //实例四 System.Threading.Tasks任务的使用
    ThreadPool.QueueUserWorkItem(SecondMethod);// 使用QueueUserWorkItem,线程池
    new Task(SecondMethod, "参数").Start();// 有参数,可以传递一个参数
    new Task(GetContextData, TaskCreationOptions.None).Start();//无参数
    Task.Factory.StartNew(GetContextData);// 创建并且启动线程(不带参数)
    Task.Factory.StartNew(SecondMethod, "");// 创建并且启动线程(带参数)
    Task.Run(() => { Console.WriteLine(" Task.Run() ..."); });//创建并且启动线程(不能带参数)
    Console.ReadLine();
    
    #endregion
    }
    public static void SecondMethod(Object state)
    {
    Console.WriteLine("执行完FirstMethod...");
    }
    public static void GetContextData()
    {
    Console.WriteLine("This is GetContextData");
    }
    
    //等待任务完成并且获取结果
    static void Main(string[] args)
    {
    #region 等待任务完成并且获取结果
    // 有返回值,只能返回一个参数
    Task<int> task = Task<int>.Factory.StartNew(x =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine("---{0}", i);
    }
    return 111;
    }, 100000);
    
    // 无返回值
    Task task1 = Task.Factory.StartNew(x =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine("---{0}", i);
    }
    return 111;
    }, 100000);
    //wait()会阻塞线程,等待task完成
    task.Wait();
    //WaitAll()会阻塞线程,等待task,task1完成
    Task.WaitAll(task, task1);
    
    //WaitAny()会阻塞线程,等待task,task1任意一个完成
    Task.WaitAny(task, task1);
    // 只有task完成才能执行下面的方法
    Console.WriteLine("等待执行完成,执行结果{0}", task.Result);
    Console.ReadLine();
    #endregion
    }
    
    // 任务完成时启动新的任务
    static void Main(string[] args)
    {
    #region 任务完成时启动新的任务
    //使用wait等待任务完成的方式会阻塞线程,这样不但增加了系统资源的浪费,也不利于延展性和伸缩性
    //以下的方式可以解决上面存在的问题
    // 实例展示
    // 创建一个新的任务
    // 都是 针对 task是否完成或者异常
    Task<int> task = Task.Run(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"{i}");
    
    }
    Console.WriteLine("第一个任务开始:" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}");
    return 10;
    });
    //创建另一个新的任务,等待上面的任务完成后,将执行的结果展示出来
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.None");
    }, TaskContinuationOptions.None);// 默认
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.OnlyOnRanToCompletion");
    
    }, TaskContinuationOptions.OnlyOnRanToCompletion);//指示只有前面的任务完成
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.NotOnRanToCompletion");
    }, TaskContinuationOptions.NotOnRanToCompletion);//指示前面的任未完成
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.OnlyOnCanceled");
    
    }, TaskContinuationOptions.OnlyOnCanceled);//指示只有任务失败等价于 = OnlyOnFaulted||NotOnRanToCompletion
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.OnlyOnFaulted");
    }, TaskContinuationOptions.OnlyOnFaulted);//之前任务执行失败
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.ExecuteSynchronously");
    }, TaskContinuationOptions.ExecuteSynchronously);//指示这个任务在第一个任务上完成
    Console.ReadLine();
    
    task.ContinueWith((x) =>
    {
    Console.WriteLine("执行的结果为:" + $"{x.Result}" + $"当前线程的Id为:{Thread.CurrentThread.ManagedThreadId}" + " 参数类型为:TaskContinuationOptions.PreferFairness");
    }, TaskContinuationOptions.PreferFairness);//指示希望这个任务尽快的执行
    Console.ReadLine();
    #endregion
    }
    
    //任务可以启动多个子任务
    static void Main(string[] args)
    {
    #region 任务可以启动多个子任务
    // 实例
    // 创建一个父任务
    Task<int[]> parentTasks = new Task<int[]>(() =>
    {
    //定义一个子任务子任务返回结果的数组,其中子任务都是异步执行
    int[] result = new int[3];
    //创建三个子任务,并且关联父任务
    new Task(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务一{i}");
    }
    result[0] = 1;
    }, TaskCreationOptions.AttachedToParent).Start();
    
    new Task(() =>
    {
    for (int i = 0; i < 5; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务二{i}");
    }
    result[1] = 2;
    }, TaskCreationOptions.AttachedToParent).Start();
    
    new Task(() =>
    {
    for (int i = 0; i < 2; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务三{i}");
    }
    result[2] = 3;
    }, TaskCreationOptions.AttachedToParent).Start();
    return result;
    });
    //父任务完成之后子任务的返回结果
    parentTasks.ContinueWith((x) =>
    {
    //遍历结果
    Array.ForEach(parentTasks.Result, (s) =>
    {
    Console.WriteLine($"结果为{s}");
    });
    });
    // 启动所有的子任务
    parentTasks.Start();
    Console.ReadLine();
    #endregion
    }
    
    //任务工厂的使用
    static void Main(string[] args)
    {
    #region 任务工厂的使用
    //实例
    // 创建一个相同配置的工厂对象
    CancellationTokenSource cts = new CancellationTokenSource();
    //创建一个统一配置的的任务工厂有返回值
    TaskFactory<int> tf = new TaskFactory<int>(
    cts.Token,
    TaskCreationOptions.AttachedToParent,
    TaskContinuationOptions.ExecuteSynchronously,
    TaskScheduler.Default
    );
    //创建三个子任务
    var childrensTask = new[]
    {
    tf.StartNew(() => {
    Console.WriteLine("子任务一");
    return 1;
    },cts.Token),
    tf.StartNew(() =>
    {
    Console.WriteLine("子任务一");
    return 55;
    }),
    tf.StartNew(() =>
    {
    Console.WriteLine("子任三");
    return 2;
    })
    };
    
    //只要有一个任务执行失败,立即取消其他的所有任务
    for (int task = 0; task < childrensTask.Length; task++)
    {
    childrensTask[task].ContinueWith((x) =>
    {
    cts.Cancel();
    }, TaskContinuationOptions.OnlyOnFaulted);
    
    }
    // 当所有的任务都完成
    tf.ContinueWhenAll(childrensTask, t =>
    {
    return childrensTask.Where(x => !x.IsCanceled || !x.IsFaulted).Max(tt => tt.Result);
    }, CancellationToken.None).ContinueWith(h =>
    {
    
    Console.WriteLine($"最大值为{h.Result}");
    });
    
    Console.ReadLine();
    #endregion
    }
    
    //任务调度器 常用
    #region 任务调度器 常用
    //实例
    //任务调度器非常灵活
    //默认情况下FcL提供了两个任务调度器
    //1 线程池任务调度器 (thread pool task scheduler)
    //2 同步上下文任务调度器(synchroizition context task scheduler)
    //所有的应用程序都是有的是线程池任务调度器
    //带界面的调度池使用上下文调度器,比如Winforms WPF
    TaskScheduler taskScheduler = TaskScheduler.Default;
    //以下任务调度器只允许不超过N个任务同时执行
    LimitedConcurrencyLevelTaskScheduler limitedConcurrencyLevelTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(2);//只允许2个任务
    
    //以下四个任务 两两执行
    Task.Factory.StartNew(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务一{i}");
    }
    }, CancellationToken.None, TaskCreationOptions.None, limitedConcurrencyLevelTaskScheduler);
    Task.Factory.StartNew(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务二{i}");
    }
    }, CancellationToken.None, TaskCreationOptions.None, limitedConcurrencyLevelTaskScheduler);
    Task.Factory.StartNew(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务三{i}");
    }
    }, CancellationToken.None, TaskCreationOptions.None, limitedConcurrencyLevelTaskScheduler);
    Task.Factory.StartNew(() =>
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"任务四{i}");
    }
    }, CancellationToken.None, TaskCreationOptions.None, limitedConcurrencyLevelTaskScheduler);
    
    Console.ReadLine();
    Console.WriteLine($"{limitedConcurrencyLevelTaskScheduler.CurrentCount}");
    Console.ReadLine();
    #endregion
    // 限制线程数的调度器
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace 多线程的学习
    {
    public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
    {
    /// <summary>Whether the current thread is processing work items.</summary>
    [ThreadStatic]
    private static bool _currentThreadIsProcessingItems;
    /// <summary>The list of tasks to be executed.</summary>
    private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
    /// <summary>The maximum concurrency level allowed by this scheduler.</summary>
    private readonly int _maxDegreeOfParallelism;
    /// <summary>Whether the scheduler is currently processing work items.</summary>
    private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)
    
    /// <summary>
    /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
    /// specified degree of parallelism.
    /// </summary>
    /// <param name="maxDegreeOfParallelism">The maximum degree of parallelism provided by this scheduler.</param>
    public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
    {
    if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
    _maxDegreeOfParallelism = maxDegreeOfParallelism;
    }
    
    /// <summary>
    /// current executing number;
    /// </summary>
    public int CurrentCount { get; set; }
    
    /// <summary>Queues a task to the scheduler.</summary>
    /// <param name="task">The task to be queued.</param>
    protected sealed override void QueueTask(Task task)
    {
    // Add the task to the list of tasks to be processed. If there aren't enough
    // delegates currently queued or running to process tasks, schedule another.
    lock (_tasks)
    {
    Console.WriteLine("Task Count : {0} ", _tasks.Count);
    _tasks.AddLast(task);
    if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
    {
    ++_delegatesQueuedOrRunning;
    NotifyThreadPoolOfPendingWork();
    }
    }
    }
    int executingCount = 0;
    private static object executeLock = new object();
    /// <summary>
    /// Informs the ThreadPool that there's work to be executed for this scheduler.
    /// </summary>
    private void NotifyThreadPoolOfPendingWork()
    {
    ThreadPool.UnsafeQueueUserWorkItem(_ =>
    {
    // Note that the current thread is now processing work items.
    // This is necessary to enable inlining of tasks into this thread.
    _currentThreadIsProcessingItems = true;
    try
    {
    // Process all available items in the queue.
    while (true)
    {
    Task item;
    lock (_tasks)
    {
    // When there are no more items to be processed,
    // note that we're done processing, and get out.
    if (_tasks.Count == 0)
    {
    --_delegatesQueuedOrRunning;
    
    break;
    }
    
    // Get the next item from the queue
    item = _tasks.First.Value;
    _tasks.RemoveFirst();
    }
    // Execute the task we pulled out of the queue
    base.TryExecuteTask(item);
    }
    }
    // We're done processing items on the current thread
    finally { _currentThreadIsProcessingItems = false; }
    }, null);
    }
    
    /// <summary>Attempts to execute the specified task on the current thread.</summary>
    /// <param name="task">The task to be executed.</param>
    /// <param name="taskWasPreviouslyQueued"></param>
    /// <returns>Whether the task could be executed on the current thread.</returns>
    protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
    
    // If this thread isn't already processing a task, we don't support inlining
    if (!_currentThreadIsProcessingItems) return false;
    
    // If the task was previously queued, remove it from the queue
    if (taskWasPreviouslyQueued) TryDequeue(task);
    
    // Try to run the task.
    return base.TryExecuteTask(task);
    }
    
    /// <summary>Attempts to remove a previously scheduled task from the scheduler.</summary>
    /// <param name="task">The task to be removed.</param>
    /// <returns>Whether the task could be found and removed.</returns>
    protected sealed override bool TryDequeue(Task task)
    {
    lock (_tasks) return _tasks.Remove(task);
    }
    
    /// <summary>Gets the maximum concurrency level supported by this scheduler.</summary>
    public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
    
    /// <summary>Gets an enumerable of the tasks currently scheduled on this scheduler.</summary>
    /// <returns>An enumerable of the tasks currently scheduled.</returns>
    protected sealed override IEnumerable<Task> GetScheduledTasks()
    {
    bool lockTaken = false;
    try
    {
    Monitor.TryEnter(_tasks, ref lockTaken);
    if (lockTaken) return _tasks.ToArray();
    else throw new NotSupportedException();
    }
    finally
    {
    if (lockTaken) Monitor.Exit(_tasks);
    }
    }
    
    }
    }
    
    //Paraller的静态For 和ForEach 和 Invoke
    static void Main(string[] args)
    {
    #region Paraller的静态For 和ForEach 和 Invoke
    
    Task.Factory.StartNew(() =>
    {
    //进程下线程
    while (true)
    {
    Thread.Sleep(1000);
    Process current = Process.GetCurrentProcess();
    ProcessThreadCollection allThreads = current.Threads;
    Console.WriteLine($"活动总线程{allThreads.Count}");
    }
    
    });
    //这个地方创建100000个线程Cpu使用率为100%
    //集合较小的可以使用这个
    //MaxDegreeOfParallelism 这个参数可以限制最大并发数目
    Parallel.For(0, 100000, new ParallelOptions() { MaxDegreeOfParallelism = 10, CancellationToken = new CancellationToken() }, i =>
    {
    Thread.Sleep(5000);
    Console.WriteLine($"当前线程{Thread.CurrentThread.ManagedThreadId}");
    
    });
    int[] s = new int[] { 1, 2, 3 };
    Parallel.ForEach(s, new ParallelOptions { MaxDegreeOfParallelism = 10 }, x => { });
    //并行执行不同的方法
    Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = 10 },
    () => { },
    () => { },
    //....
    () => { }
    
    );
    Console.ReadLine();
    
    #endregion
    }
    
    //执行定时计算限制操作 定时程序
    static void Main(string[] args)
    {
    #region 执行定时计算限制操作 定时程序
    _time = new Timer(ChangeStstus, null, Timeout.Infinite, Timeout.Infinite);
    // 设置为Timeout.Infinite 等待ChangeStstus方法完成在开始下一次回调
    _time.Change(0, Timeout.Infinite);
    // 以下不会等待ChangeStstus方法完成,就会开始第二次,一般不采用
    // _time.Change(0, 2000);
    
    
    // 除了以上方法我们还可以使用线程来做定时器
    ChnangeStatus();
    Console.WriteLine($"将在两秒后继续开始");
    Console.ReadLine();
    
    #endregion
    }
    //声明一个Time对象
    public static Timer _time;
    //这个方法签名必须和Callback的签名保持一致
    public static void ChangeStstus(Object state)
    {
    Console.WriteLine($"将在两秒后继续开始");
    // Do other work
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(1000);
    Console.WriteLine($"{i}");
    }
    
    //将在2秒后继续触发回调方法,这里不写不会再触发,一定要保证让Time对象处于存活的状态
    _time.Change(2000, Timeout.Infinite);
    }
    // 线程做定时
    public static async void ChnangeStatus()
    {
    while(true)
    {
    for (int i = 0; i < 10; i++)
    {
    Thread.Sleep(2000);
    Console.WriteLine($"执行次数中{i}");
    }
    //在不会阻塞线程的前提下延迟2秒,在while循环中2秒执行一次,会等待上面的work完成,2秒后开始下一次
    await Task.Delay(2000);
    }
    }
    
    //获取同步上下文任务调度器
    //带界面的调度池使用上下文调度器,比如Winforms WPF
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace 同步上下文任务调度器
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    //获取同步上下文任务调度器
    taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    }
    TaskScheduler taskScheduler;
    private void button1_Click(object sender, EventArgs e)
    {
    
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
    Task.Factory.StartNew(() =>
    {
    //这里不是用同步上下文调度池,需要用委托来更新ui线程
    this.Invoke(new Action(() =>
    {
    button1.Text = "线程一";
    }));
    
    }, CancellationToken.None);
    }
    
    private void button3_Click(object sender, EventArgs e)
    {
    //TaskFactory tf = new TaskFactory(
    // CancellationToken.None,
    // TaskCreationOptions.PreferFairness,
    // TaskContinuationOptions.ExecuteSynchronously,
    // taskScheduler
    // );
    //tf.StartNew(() => {
    // button1.Text = "线程er";
    
    //});
    // 使用调度池,直接在ui线程上更新
    Task.Factory.StartNew(() =>
    {
    button1.Text = "线程er";
    }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
    }
    }
    }
    

      

  • 相关阅读:
    嗯哼?考的好?不存在的。
    MyBatis的框架设计
    Mybatis数据源与连接池
    MyBatis事务管理机制
    MyBatis的SqlSession的工作过程
    Mybatis初始化机制
    [JVM-6]类加载器
    [JVM-5]类加载机制
    面试题
    TCC分布式事务的实现原理
  • 原文地址:https://www.cnblogs.com/hnzheng/p/12626978.html
Copyright © 2011-2022 走看看