我会继续翻译一些 .NET 上多线程相关的文章,不过由于原作者风格不同,术语运用方面也有差异,所以我先在这里汇总一下多线程方面相关的概念,以让读者能够有更一致的理解。(一致性也是编程过程中相当重要的,尤其是团队开发过程中,对概念一致的理解可以提高开发效率)
另一方面,这里也是我多线程相关知识体系的整理。
这篇文章就慢慢更新吧,先做个框架,想到什么再加进来。如果读者们有感觉不容易理解的概念,也可以在下面留言提出。
继续阅读...我会继续翻译一些 .NET 上多线程相关的文章,不过由于原作者风格不同,术语运用方面也有差异,所以我先在这里汇总一下多线程方面相关的概念,以让读者能够有更一致的理解。(一致性也是编程过程中相当重要的,尤其是团队开发过程中,对概念一致的理解可以提高开发效率)
另一方面,这里也是我多线程相关知识体系的整理。
这篇文章就慢慢更新吧,先做个框架,想到什么再加进来。如果读者们有感觉不容易理解的概念,也可以在下面留言提出。
继续阅读...有时候需要为程序提供多语言支持,然而 .NET 自带的方案有点不便于使用。下面介绍两个简易的工具来让这个工作更轻松些,主要针对字符串资源。
我们知道,.NET 上多语言支持的标准方式是使用 .resx 资源文件,默认语言的资源编译后嵌入主程序集,其它语言的资源文件编译成卫星程序集(satellite assembly)。
Visual Studio 自带的工具可以把对资源的使用生成代码,比如Resources.resx
文件就会生成Resources.Designer.cs
,其中包含Resources
类。资源可以通过这个类上的属性获取。大部分情况下还是挺方便的,但是对于有{0}
{1}
这种占位符的字符串就很麻烦。每次都要自己string.Format(...)
下,尤其还得先确定下里面具体是几个占位符,这是个让人恼火的事情。
某日,在 GitHub 上乱逛,发现了做 EF 7 和 ASP.NET 5 的人搞了个小工具处理这个事情:https://github.com/aspnet/EntityFramework/blob/master/tools/Resources.tt
继续阅读....NET Framework 提供了四种定时器,然而其精度都不高(一般情况下 15ms 左右),难以满足一些场景下的需求。
在进行媒体播放、绘制动画、性能分析以及和硬件交互时,可能需要 10ms 以下精度的定时器。这里不讨论这种需求是否合理,它是确实存在的问题,也有相当多的地方在讨论,说明这是一个切实的需求。然而,实现它并不是一件轻松的事情。
这里并不涉及内核驱动层面的定时器,只分析在 .NET 托管环境下应用层面的高精度定时器实现。
Windows 不是实时操作系统,所以任何方案都无法绝对保证定时器的精度,只是能尽量减少误差。所以,系统的稳定性不能完全依赖于定时器,必须考虑失去同步时的处理。
原文:http://www.albahari.com/threading/part5.aspx
专题:C#中的多线程
在这一部分,我们讨论 Framework 4.0 加入的多线程 API,它们可以充分利用多核处理器。
Parallel
类SpinLock
和 SpinWait
这些 API 可以统称为 PFX(Parallel Framework,并行框架)。Parallel
类与任务并行构造一起被称为 TPL(Task Parallel Library,任务并行库)。
Framework 4.0 也增加了一些更底层的线程构造,它们针对传统的多线程。我们之前讲过的:
SemaphoreSlim
、ManualResetEventSlim
、CountdownEvent
以及Barrier
)ThreadLocal<T>
在继续阅读前,你需要了解第 1 部分 - 第 4 部分中的基本原理,特别是锁和线程安全。
继续阅读...原文:http://www.albahari.com/threading/part4.aspx
专题:C#中的多线程
之前,我们描述了即使是很简单的赋值或更新一个字段也需要同步。尽管锁总能满足这个需求,一个存在竞争的锁意味着肯定有线程会被阻塞,就会导致由上下文切换和调度的延迟带来的开销,在高并发以及对性能要求很高的场景,这不符合需要。.NET Framework 的 非阻塞(nonblocking)同步构造能够在没有阻塞、暂停或等待的情况下完成简单的操作。
正确编写无阻塞或无锁的多线程代码是棘手的!特别是内存屏障容易用错(volatile
关键字更容易用错)。在放弃使用传统锁之前,请仔细思考是否真的需要非阻塞同步带来的性能优化。切记获得和释放一个无竞争的锁在一个 2010 时代的计算机上仅仅需要 20ns 而已。
无阻塞的方式也可以跨进程工作。一个例子就是它可以被用来读写进程间共享内存。
继续阅读...原文:http://www.albahari.com/threading/part3.aspx
专题:C#中的多线程
基于事件的异步模式(event-based asynchronous pattern,EAP)提供了一种简单的方式,让类可以提供多线程的能力,而不需要使用者显式启动和管理线程。它也提供如下的功能:
EAP 仅仅是一个模式,所以这些功能需要开发者自己实现。Framework 中仅有少数类采用这个模式,其中最常见的是 BackgroundWorker
(接下来就会讲到),以及命名空间System.Net
中的WebClient
。这个模式本质上就是:类提供一组成员,用于在内部管理多线程,类似于下边的代码:
// 这些成员来自于 WebClient 类:
public byte[] DownloadData (Uri address); // 同步版本
public void DownloadDataAsync (Uri address);
public void DownloadDataAsync (Uri address, object userToken);
public event DownloadDataCompletedEventHandler DownloadDataCompleted;
public void CancelAsync (object userState); // 取消一个操作
public bool IsBusy { get; } // 指示是否仍在运行
原文:http://www.albahari.com/threading/part2.aspx
专题:C#中的多线程
在第 1 部分:基础知识中,我们描述了如何在线程上启动任务、配置线程以及双向传递数据。同时也说明了局部变量对于线程来说是私有的,以及引用是如何在线程之间共享,允许其通过公共字段进行通信。
下一步是同步(synchronization):为期望的结果协调线程的行为。当多个线程访问同一个数据时,同步尤其重要,但是这是一件非常容易搞砸的事情。
同步构造可以分为以下四类:
Sleep
、Join
与Task.Wait
都是简单的阻塞方法。lock
(Monitor.Enter
/Monitor.Exit
)、Mutex
与 SpinLock
。非排它锁构造是Semaphore
、SemaphoreSlim
以及读写锁。Monitor
类的Wait
/ Pluse
方法。Framework 4.0 加入了CountdownEvent
与Barrier
类。Thread.MemoryBarrier
、Thread.VolatileRead
、Thread.VolatileWrite
、volatile
关键字以及Interlocked
类。原文:http://www.albahari.com/threading/
专题:C#中的多线程
C# 支持通过多线程并行执行代码,线程有其独立的执行路径,能够与其它线程同时执行。
一个 C# 客户端程序(Console 命令行、WPF 以及 Windows Forms)开始于一个单线程,这个线程(也称为“主线程”)是由 CLR 和操作系统自动创建的,并且也可以再创建其它线程。以下是一个简单的使用多线程的例子:
所有示例都假定已经引用了以下命名空间:
using System;
using System.Threading;
class ThreadTest
{
static void Main()
{
Thread t = new Thread (WriteY); // 创建新线程
t.Start(); // 启动新线程,执行WriteY()
// 同时,在主线程做其它事情
for (int i = 0; i < 1000; i++) Console.Write ("x");
}
static void WriteY()
{
for (int i = 0; i < 1000; i++) Console.Write ("y");
}
}
不少应用程序有单一实例的需求,也就是同时只能开启一个实例(一般也就是一个进程)。
实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 Mutex 工具。
Mutex是互斥体,命名的互斥体可以跨进程使用,所以可以用以实现程序单一实例这个需求。相关的例子网上应该不少,不过很多给出的例子中并没有注意到一些细节,这里就完整总结下。
继续阅读...