C#並發編程

來源:互聯網
上載者:User

標籤:同步   建立   parallel   param   show   完全   根據   列表   reads   

最近看C# 並發編程··,這裡做一下總結··多線程,非同步,並行,大部分都是最近看C#並發編程這個書涉及到的··這裡僅僅列出實現方式,書裡邊介紹的其他的東西沒有設計比如取消操作,同步操作,集合之類的東西

線程:Thread,ThreadPool,BackgroundWorker,

Thread 可以又更多控制··ThreadPool就是丟進去系統好管理線程,BackgroundWorker相當於加了事件的線程,用在thread執行函數裡邊加事件,外邊註冊加invoke就可以實作類別似backgroundworker的功能,

但是機制好像不太一樣,看了反編譯的方法invoke裡邊的代碼 帶了大量的Unmanaged 程式碼··看不大懂··,backgroundworker內部使用委託的非同步執行方式,就是begininvoke,  C#的begininvoke內部實現好像就是多線程,通過同步上下文回到ui線程實作類別似invoke 的操作

thread 和threadpool都可以傳遞一個委託進去,這樣可以通過委託做一些特殊操作··也可以直接定義個事件實現通知進度的功能

4.5的async/await  裡邊iprogress也能實作類別似報告進度功能

 代碼在winform表單裡邊執行               
 private event EventHandler myevent;
//thread myevent += delegate { Invoke(new EventHandler(delegate { Text = "threadtest"; })); }; Action myaction = new Action(() => { MessageBox.Show("delegatetest"); }); new Thread(new ParameterizedThreadStart((obj) => { //dosomthing Thread.Sleep(2000); (obj as Action)(); })).Start(myaction); new Thread(new ThreadStart(() => { //dosomething Thread.Sleep(2000); myevent?.Invoke(null, new EventArgs()); })).Start(); //backgroundworker BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += delegate { //dosomething Thread.Sleep(2000); worker.ReportProgress(100); }; worker.ProgressChanged += (send, stat) => { Text = "doworker"; }; worker.RunWorkerAsync(); //threadpool ThreadPool.QueueUserWorkItem(new WaitCallback((stat) => { //dosomthing Thread.Sleep(1000); })); //task 非同步 Task t = new Task(() => { //dosomething Thread.Sleep(3000); }); Action<Task> taction = new Action<Task>((tas) => { Text = "Task"; }); var context = TaskScheduler.FromCurrentSynchronizationContext();//這裡建立一個當前內容相關的人物調度器,其實就是當前的ui線程上下文 t.ContinueWith(taction, context);//吧上邊的調度器傳入,接著的這個人物就會用這個調度器執行,內部起始就是post方法把操作放在當前ui線程進行同步執行,這樣就不會報錯了 t.Start();//這裡是非同步方式,預設是以線程池的方式執行,如果在這裡方式ui操作會報錯線程間操作無效

之前的非同步編程,通過beginInvoke ,委託和control都有類似方法,invoke就是同步執行, begininvoke非同步執行,這個裡邊據說也是用線程池實現的非同步

            Action act = new Action(() => {                Thread.Sleep(2000);                Console.WriteLine("121231");            });            var callback = new AsyncCallback((iasynccallback) =>            {                Console.WriteLine("OK");            });            var res=act.BeginInvoke(callback, null);            Console.WriteLine("非同步測試");            act.EndInvoke(res);

上邊有Task的寫法,task通過任務調度器也就是TaskScheduler來實現調度,可以在當前線程執行,也可以通過線程池執行,這個TaskScheduler 有兩種實現,一種是用線程池實現,一種用上下文實作類別似上邊的backgroundworker,

也就是SynchronizationContext這個類,這個類又一個Post方法可以將非同步方法以同步的方式執行到指定的上下文中去,

而4.5裡邊的async/await也是以類似的方式,又上下文這個概念,這個async/await 花樣可多了···這裡就不多說了。。。

這裡舉個例子,可以把表單時間直接定義為非同步函數,這樣事件方法裡邊用await去非同步執行,而在方法中又可以直接重新整理ui,下邊的代碼是可以運行成功的· 這個完全顛覆了之前的寫法··之前的如果要進行非同步,比如線程中要更新ui就要invoke否則肯定要報錯,或者使用上面委託的非同步執行通過回呼函數的方式去執行ui重新整理應該也是要invoke的

 btn.Click += Displaywebstringlength;        async void Displaywebstringlength(object sender,EventArgs e)        {            label.Text = "Fethcing";            using (HttpClient client = new HttpClient())                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               {                string text =await client.GetStringAsync(@"https://www.baidu.com/");                label.Text = text.Length.ToString();            }        }

並行·

當有大量的不相干的事的集合要進行操作就可以用並行了也就是Parallel,這玩意內部也是用task實現的但是實現寫好複雜 沒看明白·····總之碉堡了···

也可以用對應的linq實現PLINQ,

建議使用Parallel 這個會根據cpu狀態動態調整,而plinq沒有這個考慮

比如我有一堆檔案要讀取,就可以這樣讀,或者我要檢查區域網路的那些IP能ping同,或者做一些數位彙總操作

            var nums = Enumerable.Range(1, 20);            Parallel.ForEach(nums, new Action<int>(n => Console.WriteLine(n)));//Parallel的實現            nums.AsParallel().ForAll(n => Console.WriteLine(n));//Plinq的實現

TPL資料流,就是把事件弄的想流一樣執行·· 我實在沒搞明白這玩意又啥用 反正很流弊l啦,這個東西需要用nuget下一個微軟的庫,這個庫是額外,也就是不包含在fcl中,Microsoft.Tpl.Dataflow

        static async Task Test()        {            //string uri = @"https://www.baidu.com/";            //string res = await DownloadWrithRitries(uri);            //Console.WriteLine(res);             var multiplyBlock = new TransformBlock<int, int>(item => {                item = item * 2;                Console.WriteLine(item);                return item;            });            var substractblock = new TransformBlock<int, int>(item => {                item = item - 2;                Console.WriteLine(item);                return item;            });            var opions = new DataflowLinkOptions { PropagateCompletion = true };            multiplyBlock.LinkTo(substractblock, opions);            multiplyBlock.AsObserver().OnNext(20);            multiplyBlock.Complete();            await substractblock.Completion;        }

Rx這個也是要通過nuget安裝Rx-Main,這玩意是基於IObservable<T>也就是觀察者模式·的玩意··這裡不做解釋了···主要是我的nuget沒下到這玩意·····

這裡這是列舉了這些非同步方式· 應該都支援取消操作,類似CancellationTokenSource這個類型的東西·

所以書裡邊推薦使用Task和async/await,

然後還有涉及同步方式的問題主要是阻塞鎖,非同步鎖SemaphoreSlim(其實是限流),阻塞訊號

或者使用安全執行緒集合比如ConcurrentBag,ConcurrentDictionary分別對應列表和字典的安全執行緒集合,類似的還有棧和隊列以及set的實現,這玩意內部實現好像就是monitor和innerlock配合,說是效率還可以·

·貼個代碼··這個是反編譯的ConcurrentBag的添加作業碼

private void AddInternal(ConcurrentBag<T>.ThreadLocalList list, T item){    bool flag = false;    try    {        Interlocked.Exchange(ref list.m_currentOp, 1);        if (list.Count < 2 || this.m_needSync)        {            list.m_currentOp = 0;            Monitor.Enter(list, ref flag);        }        list.Add(item, flag);    }    finally    {        list.m_currentOp = 0;        if (flag)        {            Monitor.Exit(list);        }    }}

另外微軟還有一個不可變集合庫,這玩意需要去nuget下載,都是以Immutable開頭的··

所謂的不可變意思是每次操作都返回一個全新的集合,在api實現的時候集合裡邊實現的儲存共用···具體怎麼實現就不知道了

          var stack = ImmutableStack<int>.Empty;                stack = stack.Push(13);                var biggerstack = stack.Push(7);                foreach (var item in stack)                    Console.WriteLine(item);                foreach (var item in biggerstack)                    Console.WriteLine(item);//兩個棧共用了儲存項目13的記憶體

 

C#並發編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.