狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

[轉帖]C# Task詳解

freeflydom
2023年5月20日 12:1 本文熱度 984

1、Task產生背景

Task出現之前,微軟的多線程處理方式有:Thread→ThreadPool→委托的異步調用,雖然也可以基本業務需要的多線程場景,但它們在多個線程的等待處理方面、資源占用方面、線程延續和阻塞方面、線程的取消方面等都顯得比較笨拙,在面對復雜的業務場景下,顯得有點捉襟見肘了。

ThreadPool相比Thread來說具備了很多優勢,但是ThreadPool卻又存在一些使用上的不方便。比如:

  • ThreadPool不支持線程的取消、完成、失敗通知等交互性操作;

  • ThreadPool不支持線程執行的先后次序;

正是在這種背景下,Task應運而生。Task是微軟在.Net 4.0時代推出來的,也是微軟極力推薦的一種多線程的處理方式,Task看起來像一個Thread,實際上,它是在ThreadPool的基礎上進行的封裝,Task的控制和擴展性很強,在線程的延續、阻塞、取消、超時等方面遠勝于ThreadThreadPool。以下是一個簡單的任務示例:

static void Main(string[] args)
{
    Task t = new Task(() =>
    {
        Console.WriteLine("任務開始工作……");
        Thread.Sleep(5000);  //模擬工作過程
    });
    t.Start();
    t.ContinueWith(task =>
    {
        Console.WriteLine("任務完成,完成時候的狀態為:");
        Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", 
                          task.IsCanceled, task.IsCompleted, task.IsFaulted);
    });
    Console.ReadKey();
}

2、Task使用方法

2.1 創建和啟動任務

2.1.1 無返回值的方式

方式1:調用Start方法
var t1 = new Task(() => TaskMethod("Task 1"));
t1.Start();
Task.WaitAll(t1);//等待所有任務結束

任務的狀態:Start之前為created,之后為WaitingToRun

方式2:靜態方法Run
Task.Run(() => TaskMethod("Task 2"));
方式3:TaskFactory工廠
// 方法1. TaskFactory工廠
TaskFactory taskFactory = new TaskFactory() ;
taskFactory.StartNew(() => TaskMethod("Task 3"));
// 方法2. Task.Factory屬性
Task.Factory.StartNew(() => TaskMethod("Task 3"));
//或者
var t3=Task.Factory.StartNew(() => TaskMethod("Task 3"));
Task.WaitAll(t3);

任務的狀態:Start之前為Running,之后為Running

static void Main(string[] args)
{
    var t1 = new Task(() => TaskMethod("Task 1"));
    var t2 = new Task(() => TaskMethod("Task 2"));
    t2.Start();
    t1.Start();
    Task.WaitAll(t1, t2);
    Task.Run(() => TaskMethod("Task 3"));
    Task.Factory.StartNew(() => TaskMethod("Task 4"));
    //標記為長時間運行任務,則任務不會使用線程池,而在單獨的線程中運行。
    Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
    
    #region 常規的使用方式
    Console.WriteLine("主線程執行業務處理.");
    //創建任務
    Task task = new Task(() =>
                         {
                             Console.WriteLine("使用`System.Threading.Tasks.Task`執行異步操作.");
                             for (int i = 0; i < 10; i++)
                             {
                                 Console.WriteLine(i);
                             }
                         });
    //啟動任務,并安排到當前任務隊列線程中執行任務(System.Threading.Tasks.TaskScheduler)
    task.Start();
    Console.WriteLine("主線程執行其他處理");
    task.Wait();
    #endregion
    Thread.Sleep(TimeSpan.fromSeconds(1));
    Console.ReadLine();
}
static void TaskMethod(string name)
{
    Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                      name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}
方式4:RunSynchronously同步啟動

Task實例化后調用同步方法RunSynchronously,進行線程啟動。(PS: 類似委托開啟線程,BeginInvoke是異步,而Invoke是同步)

var task = new Task(() => TaskMethod("Task 1"));
task.RunSynchronously();
async/await的實現方式
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        async static void AsyncFunction()
        {
            await Task.Delay(1);
            Console.WriteLine("使用`System.Threading.Tasks.Task`執行異步操作.");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("AsyncFunction:i={0}", i));
            }
        }
        public static void Main()
        {
            Console.WriteLine("主線程執行業務處理.");
            AsyncFunction();
            Console.WriteLine("主線程執行其他處理");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Main:i={0}", i));
            }
            Console.ReadLine();
        }
    }
}

2.1.2 帶返回值的方式

方式4:
Task<int> task = createTask("Task 1");
task.Start(); 
int result = task.Result;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        static Task<int> createTask(string name)
        {
            return new Task<int>(() => TaskMethod(name));
        }
        static void Main(string[] args)
        {
            TaskMethod("Main Thread Task");
            Task<int> task = createTask("Task 1");
            task.Start();
            int result = task.Result;
            Console.WriteLine("Task 1 Result is: {0}", result);
            task = createTask("Task 2"); 
            task.RunSynchronously(); //該任務會運行在主線程中
            result = task.Result;
            Console.WriteLine("Task 2 Result is: {0}", result);
            task = createTask("Task 3");
            Console.WriteLine(task.Status);
            task.Start();
            while (!task.IsCompleted)
            {
                Console.WriteLine(task.Status);
                Thread.Sleep(TimeSpan.fromSeconds(0.5));
            }
            Console.WriteLine(task.Status);
            result = task.Result;
            Console.WriteLine("Task 3 Result is: {0}", result);
            #region 常規使用方式
            //創建任務
            Task<int> getsumtask = new Task<int>(() => Getsum());
            //啟動任務,并安排到當前任務隊列線程中執行任務(System.Threading.Tasks.TaskScheduler)
            getsumtask.Start();
            Console.WriteLine("主線程執行其他處理");
            getsumtask.Wait(); //等待任務的完成執行過程
            Console.WriteLine("任務執行結果:{0}", getsumtask.Result.ToString());//獲得任務的執行結果
            #endregion
        }
        static int TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.fromSeconds(2));
            return 42;
        }
        static int Getsum()
        {
            int sum = 0;
            Console.WriteLine("使用`Task`執行異步操作.");
            for (int i = 0; i < 100; i++)
            {
                sum += i;
            }
            return sum;
        }
    }
}
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        public static void Main()
        {
            var ret1 = AsyncGetsum();
            Console.WriteLine("主線程執行其他處理");
            for (int i = 1; i <= 3; i++)
                Console.WriteLine("Call Main()");
            int result = ret1.Result;     //阻塞主線程
            Console.WriteLine("任務執行結果:{0}", result);
        }
        async static Task<int> AsyncGetsum()
        {
            await Task.Delay(1);
            int sum = 0;
            Console.WriteLine("使用`Task`執行異步操作.");
            for (int i = 0; i < 100; i++)
            {
                sum += i;
            }
            return sum;
        }
    }
}

2.2 線程等待、延續和組合

2.2.1 Task的線程等待和延續主要以下幾類:

  • Wait:針對單個Task的實例,可以task1.wait進行線程等待

  • WaitAny:線程列表中任何一個線程執行完畢即可執行(阻塞主線程)

  • WaitAll:線程列表中所有線程執行完畢方可執行(阻塞主線程)

  • WhenAny:與ContinueWith配合,線程列表中任何一個執行完畢,則繼續ContinueWith中的任務(開啟新線程,不阻塞主線程)

  • WhenAll:與ContinueWith配合,線程列表中所有線程執行完畢,則繼續ContinueWith中的任務(開啟新線程,不阻塞主線程)

  • ContinueWith:與WhenAny或WhenAll配合使用

  • ContinueWhenAny:等價于Task的WhenAny+ContinueWith

  • ContinueWhenAll:等價于Task的WhenAll+ContinueWith

public static void Main()
{
    //創建一個任務
    Task<int> task = new Task<int>(() =>
    {
        int sum = 0;
        Console.WriteLine("使用`Task`執行異步操作.");
        for (int i = 0; i < 100; i++)
        {
            sum += i;
        }
        return sum;
    });
    //啟動任務,并安排到當前任務隊列線程中執行任務(System.Threading.Tasks.TaskScheduler)
    task.Start();
    Console.WriteLine("主線程執行其他處理");
    //任務完成時執行處理。
    Task cwt = task.ContinueWith(t =>
    {
        Console.WriteLine("任務完成后的執行結果:{0}", t.Result.ToString());
    });
    task.Wait();
    cwt.Wait();
    
    Action<string,int> log = (name,time) =>
    {
        Console.WriteLine($"{name}任務開始...");
        Thread.Sleep(time);
        Console.WriteLine($"{name}任務結束!");
    };
    List<Task> tasks = new List<Task>
    {
        Task.Run(() => log("張三",3000)),
        Task.Run(() => log("李四",1000)),
        Task.Run(() => log("王五",2000))
    };
    //以下語句逐個測試效果
    Task.WaitAny(tasks.ToArray());
    Task.WaitAll(tasks.ToArray());
    Task.WhenAny(tasks.ToArray()).ContinueWith(x => Console.WriteLine("某個Task執行完畢"));
    Task.WhenAll(tasks.ToArray()).ContinueWith(x => Console.WriteLine("所有Task執行完畢"));
    Task.Factory.ContinueWhenAny(tasks.ToArray(), x => Console.WriteLine("某個Task執行完畢"));
    Task.Factory.ContinueWhenAll(tasks.ToArray(), x => Console.WriteLine("所有Task執行完畢"));
    Console.Read();
}

2.2.2 任務的串行

static void Main(string[] args)
{
    ConcurrentStack<int> stack = new ConcurrentStack<int>();
    //t1先串行
    var t1 = Task.Factory.StartNew(() =>
    {
        stack.Push(1);
        stack.Push(2);
    });
    //t2,t3并行執行
    var t2 = t1.ContinueWith(t =>
    {
        int result;
        stack.TryPop(out result);
        Console.WriteLine("Task t2 result={0},Thread id {1}", result, Thread.CurrentThread.ManagedThreadId);
    });
    //t2,t3并行執行
    var t3 = t1.ContinueWith(t =>
    {
        int result;
        stack.TryPop(out result);
        Console.WriteLine("Task t3 result={0},Thread id {1}", result, Thread.CurrentThread.ManagedThreadId);
    });
    //等待t2和t3執行完
    Task.WaitAll(t2, t3);
    //t4串行執行
    var t4 = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("當前集合元素個數:{0},Thread id {1}", stack.Count, Thread.CurrentThread.ManagedThreadId);
    });
    t4.Wait();
}

2.2.3 子任務

public static void Main()
{
    Task<string[]> parent = new Task<string[]>(state =>
    {
        Console.WriteLine(state);
        string[] result = new string[2];
        //創建并啟動子任務
        new Task(() => { result[0] = "我是子任務1"; }, TaskCreationOptions.AttachedToParent).Start();
        new Task(() => { result[1] = "我是子任務2"; }, TaskCreationOptions.AttachedToParent).Start();
        return result;
    }, "我是父任務,并在我的處理過程中創建多個子任務,所有子任務完成以后我才會結束執行");
    //任務完成后執行
    parent.ContinueWith(t =>
    {
        Array.ForEach(t.Result, r => Console.WriteLine(r));
    });    
    parent.Start(); //啟動父任務
    parent.Wait();//等待任務結束Wait只能等待父線程結束,沒辦法等到父線程的ContinueWith結束
    Console.ReadLine();
}

2.2.4 動態并行

TaskCreationOptions.AttachedToParent父任務等待所有子任務完成后整個任務才算完成

class Node
{
    public Node Left { get; set; }
    public Node Right { get; set; }
    public string Text { get; set; }
}
class Program
{
    static Node GetNode()
    {
        Node root = new Node
        {
            Left = new Node
            {
                Left = new Node{ Text = "L-L" },
                Right = new Node{ Text = "L-R" },
                Text = "L"
            },
            Right = new Node
            {
                Left = new Node{ Text = "R-L" },
                Right = new Node{ Text = "R-R" },
                Text = "R"
            },
            Text = "Root"
        };
        return root;
    }
    static void Main(string[] args)
    {
        Node root = GetNode();
        DisplayTree(root);
    }
    static void DisplayTree(Node root)
    {
        var task = Task.Factory.StartNew(() => DisplayNode(root),
                                        CancellationToken.None,
                                        TaskCreationOptions.None,
                                        TaskScheduler.Default);
        task.Wait();
    }
    static void DisplayNode(Node current)
    {
        if (current.Left != null)
            Task.Factory.StartNew(() => DisplayNode(current.Left),
                                        CancellationToken.None,
                                        TaskCreationOptions.AttachedToParent,
                                        TaskScheduler.Default);
        if (current.Right != null)
            Task.Factory.StartNew(() => DisplayNode(current.Right),
                                        CancellationToken.None,
                                        TaskCreationOptions.AttachedToParent,
                                        TaskScheduler.Default);
        Console.WriteLine("當前節點的值為{0};處理的ThreadId={1}", current.Text, Thread.CurrentThread.ManagedThreadId);
    }
}

2.3 取消任務

private static int TaskMethod(string name, int seconds, CancellationToken token)
{
    Console.WriteLine("Task {0} 正在運行,當前線程id {1}. Is thread pool thread: {2}",
        name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
    for (int i = 0; i < seconds; i++)
    {
        Thread.Sleep(TimeSpan.fromSeconds(1));
        if (token.IsCancellationRequested) return -1;
    }
    return 42 * seconds;
}
private static void Main(string[] args)
{
    var cts = new CancellationTokenSource();
    var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token);
    Console.WriteLine(longTask.Status);
    cts.Cancel();
    Console.WriteLine(longTask.Status);
    Console.WriteLine("第一個任務在執行前已被取消");
    cts = new CancellationTokenSource();
    longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token);
    longTask.Start();
    for (int i = 0; i < 5; i++)
    {
        Thread.Sleep(TimeSpan.fromSeconds(0.5));
        Console.WriteLine(longTask.Status);
    }
    cts.Cancel();
    for (int i = 0; i < 5; i++)
    {
        Thread.Sleep(TimeSpan.fromSeconds(0.5));
        Console.WriteLine(longTask.Status);
    }
    Console.WriteLine("任務已完成,結果為 {0}.", longTask.Result);
}

2.4 處理異常

2.4.1 單個任務

static int TaskMethod(string name, int seconds)
{
    Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
        name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
    Thread.Sleep(TimeSpan.fromSeconds(seconds));
    throw new Exception("Boom!");
    return 42 * seconds;
}
static void Main(string[] args)
{
    try
    {
        Task<int> task = Task.Run(() => TaskMethod("Task 2", 2));
        int result = task.GetAwaiter().GetResult();
        Console.WriteLine("Result: {0}", result);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Task 2 Exception caught: {0}", ex.Message);
    }
    Console.WriteLine("----------------------------------------------");
    Console.ReadLine();
}

2.4.2 多個任務

static int TaskMethod(string name, int seconds)
{
    Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
        name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
    Thread.Sleep(TimeSpan.fromSeconds(seconds));
    throw new Exception(string.Format("Task {0} Boom!", name));
    return 42 * seconds;
}
public static void Main(string[] args)
{
    try
    {
        var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
        var t2 = new Task<int>(() => TaskMethod("Task 4", 2));
        var complexTask = Task.WhenAll(t1, t2);
        var exceptionHandler = complexTask.ContinueWith(t =>
                Console.WriteLine("Result: {0}", t.Result),
                TaskContinuationOptions.OnlyOnFaulted
            );
        t1.Start();
        t2.Start();
        Task.WaitAll(t1, t2);
    }
    catch (AggregateException ex)
    {
        ex.Handle(exception =>
        {
            Console.WriteLine(exception.Message);
            return true;
        });
    }
}

2.4.3 async/await的方式

class Program
{
    static async Task ThrowNotImplementedExceptionAsync()
    {
        throw new NotImplementedException();
    }
    static async Task ThrowInvalidOperationExceptionAsync()
    {
        throw new InvalidOperationException();
    }
    static async Task Normal()
    {
        await Fun();
    }
    static Task Fun()
    {
        return Task.Run(() =>
        {
            for (int i = 1; i <= 10; i++)
            {
                Console.WriteLine("i={0}", i);
                Thread.Sleep(200);
            }
        });
    }
    static async Task ObserveOneExceptionAsync()
    {
        var task1 = ThrowNotImplementedExceptionAsync();
        var task2 = ThrowInvalidOperationExceptionAsync();
        var task3 = Normal();
        try
        {
            Task allTasks = Task.WhenAll(task1, task2, task3); //異步的方式
            await allTasks;
            //Task.WaitAll(task1, task2, task3); //同步的方式
        }
        catch (NotImplementedException ex)
        {
            Console.WriteLine("task1 任務報錯!");
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine("task2 任務報錯!");
        }
        catch (Exception ex)
        {
            Console.WriteLine("任務報錯!");
        }
    }
    public static void Main()
    {
        Task task = ObserveOneExceptionAsync();
        Console.WriteLine("主線程繼續運行........");
        task.Wait();
    }
}

2.5 Task.fromResult

此方法創建一個Task<TResult>對象,該對象的Task<TResult>.Result屬性為result,其Status屬性為RanToCompletion。 當立即知道任務的返回值而不執行更長的代碼路徑時,通常使用方法。

class Program
{
    static IDictionary<string, string> cache = new Dictionary<string, string>()
    {
        {"0001","A"}, {"0002","B"}, {"0003","C"},
        {"0004","D"}, {"0005","E"}, {"0006","F"}
    };
    public static void Main()
    {
        Task<string> task = GetValuefromCache("0006");
        Console.WriteLine("主程序繼續執行。。。。");
        string result = task.Result;
        Console.WriteLine("result={0}", result);
    }
    private static Task<string> GetValuefromCache(string key)
    {
        Console.WriteLine("GetValuefromCache開始執行。。。。");
        string result = string.Empty;
        //Task.Delay(5000);
        Thread.Sleep(5000);
        Console.WriteLine("GetValuefromCache繼續執行。。。。");
        if (cache.TryGetValue(key, out result))
        {
            return Task.fromResult(result);
        }
        return Task.fromResult("");
    }
}

2.6 Factory.fromAsync

APM模式(委托)轉換為任務,BeginXXXEndXXX

2.6.1 帶回調方式的

class Program
{
    private delegate string AsynchronousTask(string threadName);
    private static string Test(string threadName)
    {
        Console.WriteLine("開始...");
        Console.WriteLine("線程池是線程嗎: {0}", Thread.CurrentThread.IsThreadPoolThread);
        Thread.Sleep(TimeSpan.fromSeconds(2));
        Thread.CurrentThread.Name = threadName;
        return string.Format("線程名稱: {0}", Thread.CurrentThread.Name);
    }
    private static void Callback(IAsyncResult ar)
    {
        Console.WriteLine("開始一個回調...");
        Console.WriteLine("傳遞給callbak的狀態: {0}", ar.AsyncState);
        Console.WriteLine("線程池是線程嗎: {0}", Thread.CurrentThread.IsThreadPoolThread);
        Console.WriteLine("線程池工作線程id: {0}", Thread.CurrentThread.ManagedThreadId);
    }
    //執行的流程是:先執行Test--->Callback--->task.ContinueWith
    static void Main(string[] args)
    {
        AsynchronousTask d = Test;
        Console.WriteLine("Option 1");
        Task<string> task = Task<string>.Factory.fromAsync(
            d.BeginInvoke("AsyncTaskThread", Callback, "委托異步調用"), d.EndInvoke);
        task.ContinueWith(t => Console.WriteLine("完成回調, 現在繼續! Result: {0}", t.Result));
        while (!task.IsCompleted)
        {
            Console.WriteLine(task.Status);
            Thread.Sleep(TimeSpan.fromSeconds(0.5));
        }
        Console.WriteLine(task.Status);
    }
}

2.6.2 不帶回調方式的

class Program
{
    private delegate string AsynchronousTask(string threadName);
    private static string Test(string threadName)
    {
        Console.WriteLine("開始...");
        Console.WriteLine("線程池是線程嗎: {0}", Thread.CurrentThread.IsThreadPoolThread);
        Thread.Sleep(TimeSpan.fromSeconds(2));
        Thread.CurrentThread.Name = threadName;
        return string.Format("線程名稱: {0}", Thread.CurrentThread.Name);
    }
    //執行的流程是:先執行Test--->task.ContinueWith
    static void Main(string[] args)
    {
        AsynchronousTask d = Test;
        Task<string> task = Task<string>.Factory.fromAsync(
            d.BeginInvoke, d.EndInvoke, "AsyncTaskThread", "委托異步調用");
        task.ContinueWith(t => Console.WriteLine("任務完成,現在運行一個延續! Result: {0}", t.Result));
        while (!task.IsCompleted)
        {
            Console.WriteLine(task.Status);
            Thread.Sleep(TimeSpan.fromSeconds(0.5));
        }
        Console.WriteLine(task.Status);
    }
}

2.6.3 Task啟動帶參數和返回值的函數任務

方法1
private int MyTest(object i)
{
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = true;
    }));
    System.Threading.Thread.Sleep(3000);
    MessageBox.Show("hello:" + i);
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = false;
    }));
    return 0;
}
private void Call()
{
    //Func<string, string> funcOne = delegate(string s){ return "fff"; };
    object i = 55;
    var t = Task<int>.Factory.StartNew(new Func<object, int>(MyTest), i);
}
方法2
private async Task<int> MyTest(object i)
{
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = true;
    }));
    HttpClient client = new HttpClient();
    var a = await client.GetAsync("http://www.baidu.com");
    Task<string> s = a.Content.ReadAsStringAsync();
    MessageBox.Show (s.Result);
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = false;
    }));
    return 0;
}
async private void Call()
{
    object i = 55;
    var t = Task<Task<int>>.Factory.StartNew(new Func<object, Task<int>>(MyTest), i);
}
方法3
private async void MyTest()
{
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = true;
    }));
    HttpClient client = new HttpClient();
    var a = await client.GetAsync("http://www.baidu.com");
    Task<string> s = a.Content.ReadAsStringAsync();
    MessageBox.Show (s.Result);
    this.Invoke(new Action(() =>
    {
        pictureBox1.Visible = false;
    }));
}
private void Call()
{
    var t = Task.Run(new Action(MyTest));
    //相當于
    //Thread th= new Thread(new ThreadStart(MyTest));
    //th.Start();
}

2.7 使用IProgress

IProgress<in T>只提供了一個方法void Report(T value),通過Report方法把一個T類型的值報告給IProgress,然后IProgress<in T>的實現類Progress<in T>的構造函數接收類型為Action<T>的形參,通過這個委托讓進度顯示在UI界面中。

class Program
{
    static void DoProcessing(IProgress<int> progress)
    {
        for (int i = 0; i <= 100; ++i)
        {
            Thread.Sleep(100);
            if (progress != null)
            {
                progress.Report(i);
            }
        }
    }
    static async Task Display()
    {
        //當前線程
        var progress = new Progress<int>(percent =>
        {
            Console.Clear();
            Console.Write("{0}%", percent);
        });
        //線程池線程
        await Task.Run(() => DoProcessing(progress));
        Console.WriteLine("");
        Console.WriteLine("結束");
    }
    public static void Main()
    {
        Task task = Display();
        task.Wait();
    }
}


---------------------------------

https://www.cnblogs.com/zhaoshujie/p/11082753.html


該文章在 2023/5/20 12:01:34 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved