搜索
首页后端开发C#.Net教程C#并发编程·经典实例读书笔记

前言

最近在看《C# 并发编程 · 经典实例》这本书,这不是一本理论书,反而这是一本主要讲述怎么样更好的使用好目前 C#.NET 为我们提供的这些 API 的一本书,书中绝大部分是一些实例,在日常开发中还是经常会使用到。

书中一些观点还是比较赞同,比如作者说目前绝大多数的图书对关于并发多线程等这些内容放到最后,而缺少一本介绍并发编程的入门指引和参考。

另外一个观点是绝大多数国内的技术人员认为技术越底层就牛逼,而做上层应用的就是“码农”,作者反对了这一观点,其实能利用好现有的库也是一种能力,虽然说理解基础知识对日常生活仍然有帮助,但最好从更高级的抽象概念来学习。

异步基础

任务暂停,休眠

异步方式暂停或者休眠任务,可以使用 Task.Delay();

static async Task<T> DelayResult<T>(T result, TimeSpan delay) {
    await Task.Delay(delay);
    return result;
}

异步重试机制

一个简单的指数退避策略,重试的时间会逐次增加,在访问 Web 服务时,一般采用此种策略。

static async Task<string> DownloadString(string uri) {
    using (var client = new HttpClient()) {
        var nextDealy = TimeSpan.FromSeconds(1);
        for (int i = 0; i != 3; ++i) {
            try {
                return await client.GetStringAsync(uri);
            }
            catch {
            }
            await Task.Delay(nextDealy);
            nextDealy = nextDealy + nextDealy;
        }
        //最后重试一次,抛出出错信息           
        return await client.GetStringAsync(uri);
    }
}

报告进度

异步操作中,经常需要展示操作进度,可以使用 IProcess8742468051c85b06f0a0af9e3e506b5c 和 Process8742468051c85b06f0a0af9e3e506b5c。

static async Task MyMethodAsync(IProgress<double> progress) {
    double precentComplete = 0;
    bool done = false;
    while (!done) {
        await Task.Delay(100);
        if (progress != null) {
            progress.Report(precentComplete);
        }
        precentComplete++;
        if (precentComplete == 100) {
            done = true;
        }
    }
}
public static void Main(string[] args) {
    Console.WriteLine("starting...");
    var progress = new Progress<double>();
    progress.ProgressChanged += (sender, e) => {
        Console.WriteLine(e);
    };
    MyMethodAsync(progress).Wait();
    Console.WriteLine("finished");
}

等待一组任务

同时执行几个任务,等待他们全部完成

Task task1 = Task.Delay(TimeSpan.FromSeconds(1));
Task task2 = Task.Delay(TimeSpan.FromSeconds(2));
Task task3 = Task.Delay(TimeSpan.FromSeconds(1));
Task.WhenAll(task1, task2, task3).Wait();

等待任意一个任务完成

执行若干任务,只需要对其中一个的完成进行响应。主要用于对一个操作进行多种独立的尝试,只要其中一个尝试完成,任务就算完成。

static async Task<int> FirstResponseUrlAsync(string urlA, string urlB) {
    var httpClient = new HttpClient();
    Task<byte[]> downloadTaskA = httpClient.GetByteArrayAsync(urlA);
    Task<byte[]> downloadTaskB = httpClient.GetByteArrayAsync(urlB);
    Task<byte[]> completedTask = await Task.WhenAny(downloadTaskA, downloadTaskB);
    byte[] data = await completedTask;
    return data.Length;
}

集合

不可变栈和队列

需要一个不会经常修改,可以被多个线程安全访问的栈和队列。他们的API和 Stack8742468051c85b06f0a0af9e3e506b5c 和 Queue8742468051c85b06f0a0af9e3e506b5c 非常相似。性能上,不可变栈(LIFO)和队列(FIFO)与标准的栈和队列具有相同的时间复杂度。但是在需要频繁修改的简单情况下,标准栈和队列速度更快。

在内部实现上,当对一个对象进行覆盖(重新赋值)的时候,不可变集合采用的是返回一个修改过的集合,原始集合引用是不变化的,也就是说如果另外一个变量引用了相同的对象,那么它(另外的变量)是不会变化的。

ImmutableStack

var stack = ImmutableStack<int>.Empty;
stack = stack.Push(11);  
var biggerstack = stack.Push(12);
foreach (var item in biggerstack) {
    Console.WriteLine(item);
}  // output: 12 11
int lastItem;
stack = stack.Pop(out lastItem);
Console.WriteLine(lastItem);  //output: 11

实际上,两个栈内部共享了存储 11 的内存,这种实现方式效率很高,而且每个实例都是线程安全的。

ImmutableQueue

var queue = ImmutableQueue<int>.Empty;
queue = queue.Enqueue(11);
queue = queue.Enqueue(12);
foreach (var item in queue) {
    Console.WriteLine(item);
} // output: 11  12
int nextItem;
queue = queue.Dequeue(out nextItem);
Console.WriteLine(nextItem); //output: 11

不可变列表和集合

ImmutableList

时间复杂度

911.jpg

有些时候需要这样一个数据结构:支持索引,不经常修改,可以被多线程安全的访问。

var list = ImmutableList<int>.Empty;
list = list.Insert(0, 11);
list = list.Insert(0, 12);
foreach (var item in list) {
    Console.WriteLine(item);
} // 12 11

ImmutableList8742468051c85b06f0a0af9e3e506b5c 可以索引,但是注意性能问题,不能用它来简单的替代 List8742468051c85b06f0a0af9e3e506b5c。它的内部实现是用的二叉树组织的数据,这么做是为了让不同的实例之间共享内存。

ImmutableHashSet

有些时候需要这样一个数据结构:不需要存放重复内容,不经常修改,可以被多个线程安全访问。时间复杂度 O(log N)。

var set = ImmutableHashSet<int>.Empty;
set = set.Add(11);
set = set.Add(12);
foreach (var item in set) {
    Console.WriteLine(item);
} // 11 12 顺序不定

线程安全字典

一个线程安全的键值对集合,多个线程读写仍然能保持同步。

ConcurrentDictionary

混合使用了细粒度的锁定和无锁技术,它是最实用的集合类型之一。

var dictionary = new ConcurrentDictionary<int, string>();
dictionary.AddOrUpdate(0, key => "Zero", (key, oldValue) => "Zero");

如果多个线程读写一个共享集合,实用 ConcurrentDictionary8c189faf63255a5ea96468ba21dd0564 是最合适的。如果不会频繁修改,那么更适合使用 ImmutableDictionary8c189faf63255a5ea96468ba21dd0564 。

它最适合用于在需要共享数据的场合,即多个线程共享一个集合,如果一些线程只添加元素一些线程只移除元素,那最好使用 生产者/消费者集合(BlockingCollection8742468051c85b06f0a0af9e3e506b5c)。

初始化共享资源

程序多个地方使用一个值,第一次访问时对它进行初始化。

static int _simpleVluae;
static readonly Lazy<Task<int>> shardAsyncInteger =
    new Lazy<Task<int>>(async () => {
        await Task.Delay(2000).ConfigureAwait(false);
        return _simpleVluae++;
    });
public static void Main(string[] args) {

    int shareValue = shardAsyncInteger.Value.Result;
    Console.WriteLine(shareValue); // 0
    shareValue = shardAsyncInteger.Value.Result;
    Console.WriteLine(shareValue); // 0
    shareValue = shardAsyncInteger.Value.Result;
    Console.WriteLine(shareValue); // 0
}

以上就是C#并发编程·经典实例读书笔记的内容,更多相关内容请关注PHP中文网(www.php.cn)!


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
c#vs. .net:澄清关键差异和相似之处c#vs. .net:澄清关键差异和相似之处May 01, 2025 am 12:12 AM

C#是一种编程语言,而.NET是一个软件框架。1.C#由微软开发,适用于多平台开发。2..NET提供类库和运行时环境,支持多语言。两者协同工作,构建现代应用。

超越炒作:评估C#.NET的当前作用超越炒作:评估C#.NET的当前作用Apr 30, 2025 am 12:06 AM

C#.NET是一个强大的开发平台,结合了C#语言和.NET框架的优势。1)它广泛应用于企业应用、Web开发、游戏开发和移动应用开发。2)C#代码编译成中间语言后由.NET运行时环境执行,支持垃圾回收、类型安全和LINQ查询。3)使用示例包括基本控制台输出和高级LINQ查询。4)常见错误如空引用和类型转换错误可以通过调试器和日志记录解决。5)性能优化建议包括异步编程和优化LINQ查询。6)尽管面临竞争,C#.NET通过不断创新保持其重要地位。

C#.NET的未来:趋势和机遇C#.NET的未来:趋势和机遇Apr 29, 2025 am 12:02 AM

C#.NET的未来趋势主要集中在云计算、微服务、AI和机器学习集成以及跨平台开发三个方面。1)云计算和微服务:C#.NET通过Azure平台优化云环境表现,支持构建高效微服务架构。2)AI和机器学习集成:借助ML.NET库,C#开发者可在应用中嵌入机器学习模型,推动智能化应用发展。3)跨平台开发:通过.NETCore和.NET5 ,C#应用可在Windows、Linux和macOS上运行,扩展部署范围。

C#.NET开发今天:趋势和最佳实践C#.NET开发今天:趋势和最佳实践Apr 28, 2025 am 12:25 AM

C#.NET开发的最新动态和最佳实践包括:1.异步编程提高应用响应性,使用async和await关键字简化非阻塞代码;2.LINQ提供强大查询功能,通过延迟执行和表达式树高效操作数据;3.性能优化建议包括使用异步编程、优化LINQ查询、合理管理内存、提升代码可读性和维护性、以及编写单元测试。

C#.NET:使用.NET生态系统构建应用程序C#.NET:使用.NET生态系统构建应用程序Apr 27, 2025 am 12:12 AM

如何利用.NET构建应用?使用.NET构建应用可以通过以下步骤实现:1)了解.NET基础知识,包括C#语言和跨平台开发支持;2)学习核心概念,如.NET生态系统的组件和工作原理;3)掌握基本和高级用法,从简单控制台应用到复杂的WebAPI和数据库操作;4)熟悉常见错误与调试技巧,如配置和数据库连接问题;5)应用性能优化与最佳实践,如异步编程和缓存。

C#作为多功能.NET语言:应用程序和示例C#作为多功能.NET语言:应用程序和示例Apr 26, 2025 am 12:26 AM

C#在企业级应用、游戏开发、移动应用和Web开发中均有广泛应用。1)在企业级应用中,C#常用于ASP.NETCore开发WebAPI。2)在游戏开发中,C#与Unity引擎结合,实现角色控制等功能。3)C#支持多态性和异步编程,提高代码灵活性和应用性能。

C#.NET用于网络,桌面和移动开发C#.NET用于网络,桌面和移动开发Apr 25, 2025 am 12:01 AM

C#和.NET适用于Web、桌面和移动开发。1)在Web开发中,ASP.NETCore支持跨平台开发。2)桌面开发使用WPF和WinForms,适用于不同需求。3)移动开发通过Xamarin实现跨平台应用。

C#.NET生态系统:框架,库和工具C#.NET生态系统:框架,库和工具Apr 24, 2025 am 12:02 AM

C#.NET生态系统提供了丰富的框架和库,帮助开发者高效构建应用。1.ASP.NETCore用于构建高性能Web应用,2.EntityFrameworkCore用于数据库操作。通过理解这些工具的使用和最佳实践,开发者可以提高应用的质量和性能。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具