C#并发编程

摘要:
{MessageBox.Show(“delegatetest”);newThread(newParameterizedThreadStart((obj)=>newThread(newThreadStart()=>worker.RunWorkerSync();

最近看C# 并发编程··,这里做一下总结··多线程,异步,并行,大部分都是最近看C#并发编程这个书涉及到的··这里仅仅列出实现方式,书里边介绍的其他的东西没有涉及比如取消操作,同步操作,集合之类的东西

线程:Thread,ThreadPool,BackgroundWorker,

Thread 可以又更多控制··ThreadPool就是丢进去系统好管理线程,BackgroundWorker相当于加了事件的线程,用在thread执行函数里边加事件,外边注册加invoke就可以实现类似backgroundworker的功能,

但是机制好像不太一样,看了反编译的方法invoke里边的代码 带了大量的非托管代码··看不大懂··,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的实现
//任务并行执行       

Action maction = () => {
Console.WriteLine("ParelTest");
};
Parallel.Invoke(maction);

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#并发编程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Nginx+keepalived的高可用集群(一、基本概念介绍)window.opener方法的使用 js跨域下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c#实现多线程代码例子

相信大家都有用过网际快车等下载资源的经历,它里面是可以设置线程数的(近年版本默认是10,曾经默认是5)。它会将文件分成与线程数相同的部分,然后每个线程下载自己的那一部分,这样下载效率就有可能提高。相信大家都有加多线程数,提升下载效率的经历。但细心的用户会发现,在带宽一定的情况下,并不是线程越多,速度越快,而是在某一点达到峰值。在C#中用多线程并不难实现。它...

Java线上应用故障排查之一:高CPU占用

转自: http://blog.csdn.net/blade2001/article/details/9065985 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环。 (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen) 以我们最近出现的一个实际故障...

JS 页面弹窗,弹出DIV并使整个页面背景变暗的功能的实现代码

首先写一个遮罩层div,然后再写一个弹窗的div <!-- 遮罩层 --><div style="background: #000; position: absolute; left: 0px; top: 0px; 100%; filter: alpha(opacity=30); opacity: 0.3; display: non...

CSS样式表定义让文字自动适应Table宽度

以下的例子是用样式实现,文字自动适应Table的宽度,并且超出的宽度的文字自动隐藏。IE下面还可以自动出现...的省略符号.关键样式:table-layout:fixed 固定布局的算法,则表格被呈递的默认宽度为 100% (For IE,Mozilla)text-overflow:ellipsis 当对象内文本溢出时显示省略标记(...) (For IE...

WebService处理大数据量数据

在通过WebService处理大数据量数据时出现如下错误: soap fault: 运行配置文件中指定的扩展时出现异常。 ---> 超过了最大请求长度。 解决方法: 因为上传的文件大于系统默认配置的值,asp.net web service默认的请求长度是4M。 1、针对单个项目,只需修改Web.config就可以了: 修改配置可以在web.conf...

前端vue以模板方式导出word----依赖 docxtemplater

原理:需要将页面中table导出一个word文件,在本地做好一个word模板,定义好变量,以这个模板文件为导出依赖,将后台获取的变量添加进去。 需求:将“伦理审查批件”导出为word 导出word和pdf对实际工作的影响:   上一篇博客实现了前端导出pdf,但是后来发现,当意见内容特别多的时候,pdf分页会有点问题:      而word会自动处理这种...