前言

学习C#两个多月了,像当初实习做PHP开发一样,也是由着一个个Feature需求,慢慢掌握了很多相关的编程技巧。本次主要记录下学习C# 多线程的相关知识。

参考书籍:《Csharp高级编程(第7版)》

1.使用线程的原因

不过运行多个线程也要注意一些问题:他们可以同时运行,但是如果线程访问相同的数据,就很容易出问题,必须实现同步机制

 2.理解线程

线程是程序中独立的指令流。C#编写的程序都有一个入口点(即Main()方法),程序从该方法的第一条开始执行,直到方法返回为止。这种程序结构非常适合用于一个有任务序列的程序,但是程序常常需要同时完成多个任务。

这就要用到多个线程,比如Word的拼写检查器的工作原理是这样的:一个线程等待用户输入,另一个线程进行后台搜索,第3个线程将写入的数据保存在临时文件中,第4个线程从Internet上下载其他数据。

理解线程很重要的一点其实是理解线程和进程的关系:

3.创建线程的方式

  • 异步委托

创建线程的一种简单地方式是定义委托,并异步调用它。委托是方法的类型安全的引用,它使用线程池来完成异步任务。

代码实例:

使用投票的例子,并检查委托是否完成了它的任务。等待异步委托结果的四种方式:

(1)轮询

Delegate类提供了BeginInvoke()方法,通过其返回类型IAsyncResult ,可以获取委托的相关信息,并检验它是否完成了任务。只要委托没有完成其任务,程序的主线程就继续执行while循环。

(2)等待句柄

使用与IAsyncResult 相关联的等待句柄。使用AsyncWaitHandle属性可以访问等待句柄,该属性可以返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。

(3)异步回调

(4)Lambda表达式 

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics; namespace Wrox.ProCSharp.Threading
{
class Program
{
static int TakesAWhile(int data, int ms)
{
Console.WriteLine("TakesAWhile started");
Thread.Sleep(ms);
Console.WriteLine("TakesAWhile completed");
return ++data;
}

     //要从委托中调用这个方法,必须定义一个有相同参数和返回类型的的委托
public delegate int TakesAWhileDelegate(int data, int ms); static void Main()
{
// synchronous
// TakesAWhile(1, 3000);
TakesAWhileDelegate d1 = TakesAWhile; // (1)polling轮询
//IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);
//while (!ar.IsCompleted)
//{
// // doing something else
// Console.Write(".");
// Thread.Sleep(50);
//}
//int result = d1.EndInvoke(ar);
//Console.WriteLine("result: {0}", result); // (2)wait handle
//IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);
//while (true)
//{
// Console.Write(".");
// if (ar.AsyncWaitHandle.WaitOne(50, false))
// {
// Console.WriteLine("Can get the result now");
// break;
// }
//}
//int result = d1.EndInvoke(ar);
//Console.WriteLine("result: {0}", result); // (3)async callback
//d1.BeginInvoke(1, 3000, TakesAWhileCompleted, d1);
//for (int i = 0; i < 100; i++)
//{
// Console.Write(".");
// Thread.Sleep(50);
//} //(4)Lambda expression:可以直接访问作用域外的变量d1,所以不需要把一个值赋予BeginInvoke()方法的最后一个参数
d1.BeginInvoke(1, 3000,
ar =>
{
int result = d1.EndInvoke(ar);
Console.WriteLine("result: {0}", result);
},
null);
for (int i = 0; i < 100; i++)
{
Console.Write(".");
Thread.Sleep(50);
} } static void TakesAWhileCompleted(IAsyncResult ar)
{
if (ar == null) throw new ArgumentNullException("ar"); TakesAWhileDelegate d1 = ar.AsyncState as TakesAWhileDelegate;
Trace.Assert(d1 != null, "Invalid object type"); int result = d1.EndInvoke(ar);
Console.WriteLine("result: {0}", result);
}
}
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace Wrox.ProCSharp.Threading
{
public class MyThread
{
private string data; public MyThread(string data)
{
this.data = data;
} public void ThreadMain()
{
Console.WriteLine("Running in a thread, data: {0}", data);
}
} public struct Data
{
public string Message;
} class Program
{
static void Main()
{
FirstThread(); //var t1 = new Thread(Prio);
//t1.Name = "First"; //var t2 = new Thread(Prio);
//t2.Name = "Second";
//t1.Priority = ThreadPriority.Highest;
//t2.Priority = ThreadPriority.Lowest; //t1.Start();
//t2.Start(); //var t1 = new Thread(ThreadMain);
//t1.Name = "MyNewThread1";
//t1.IsBackground = true;
//t1.Start();
//Console.WriteLine("Main thread ending now..."); //var d = new Data { Message = "Info" };
//var t2 = new Thread(ThreadMainWithParameters);
//t2.Start(d); //var obj = new MyThread("info");
//var t3 = new Thread(obj.ThreadMain);
//t3.Start();
} static void Prio()
{
for (int i = 0; i < 10000; i++)
{
Console.WriteLine("{0}, {1}", Thread.CurrentThread.Name, i);
}
} static void ThreadMain()
{
Console.WriteLine("Thread {0} started", Thread.CurrentThread.Name);
Thread.Sleep(3000);
// Console.WriteLine("Running in the thread {0}, id: {1}.", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Thread {0} completed", Thread.CurrentThread.Name);
} static void ThreadMainWithParameters(object o)
{
Data d = (Data)o;
Console.WriteLine("Running in a thread, received {0}", d.Message);
} static void FirstThread()
{
new Thread(() => Console.WriteLine("Running in a thread, id: {0}", Thread.CurrentThread.ManagedThreadId)).Start(); Console.WriteLine("This is the main thread, id: {0}", Thread.CurrentThread.ManagedThreadId);
}
}
}

运行结果:

代码实例:

using System;
using System.Threading; namespace Wrox.ProCSharp.Threading
{
class Program
{
static void Main()
{
int nWorkerThreads;
int nCompletionPortThreads;
ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPortThreads);
Console.WriteLine("Max worker threads: {0}, I/O completion threads: {1}", nWorkerThreads, nCompletionPortThreads); for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(JobForAThread); } Thread.Sleep(3000);
} static void JobForAThread(object state)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("loop {0}, running inside pooled thread {1}", i,
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(50);
} }
}
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO; namespace TaskSamples
{
class Program
{
static void Main()
{
// ParallelDemo(); SimpleTask();
// ContinuationTask();
// ParentAndChild();
// ResultsFromTasks(); Thread.Sleep(5000); //ParentAndChild(); // HierarchyTasks("c:\\"); //Parallel.f
//Task t1 = new Task(() => Console.WriteLine("running in a task"));
//Task t2 = new Task(() => Console.WriteLine("running in a task")); //for (int i = 0; i < 10; i++)
//{
// Task t1 = new Task(o =>
// {
// Console.WriteLine("running in a task {0}", Thread.CurrentThread.ManagedThreadId);
// Thread.Sleep(500);
// Console.WriteLine("still running {0}", Thread.CurrentThread.ManagedThreadId);
// }, "data", TaskCreationOptions.None);
// // t1.RunSynchronously();
// t1.Start(); //} //Console.WriteLine("start sleep main");
//Thread.Sleep(3000);
//Console.WriteLine("main thread");
} static void ResultsFromTasks()
{
var t1 = new Task<Tuple<int,int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));
t1.Start();
Console.WriteLine(t1.Result);
t1.Wait();
Console.WriteLine("result from task: {0} {1}", t1.Result.Item1, t1.Result.Item2);
} static Tuple<int, int> TaskWithResult(object division)
{
Tuple<int, int> div = (Tuple<int, int>)division;
int result = div.Item1 / div.Item2;
int reminder = div.Item1 % div.Item2;
Console.WriteLine("task creates a result..."); return Tuple.Create<int, int>(result, reminder);
} static void SimpleTask()
{
// using task factory
TaskFactory tf = new TaskFactory();
Task t1 = tf.StartNew(TaskMethod); // using the task factory via a task
Task t2 = Task.Factory.StartNew(TaskMethod); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // using Task constructor
Task t3 = new Task(TaskMethod);
// t3.Start();
t3.RunSynchronously(); Task t4 = new Task(TaskMethod, TaskCreationOptions.PreferFairness);
t4.Start(); } static void ContinuationTask()
{
Task t1 = new Task(DoOnFirst);
Task t2 = t1.ContinueWith(DoOnSecond);
Task t3 = t1.ContinueWith(DoOnSecond);
Task t4 = t2.ContinueWith(DoOnSecond);
Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);
t1.Start(); Thread.Sleep(5000); } static void DoOnFirst()
{
Console.WriteLine("doing some task {0}", Task.CurrentId);
Thread.Sleep(3000);
} static void DoOnSecond(Task t)
{
Console.WriteLine("task {0} finished", t.Id);
Console.WriteLine("this task id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
Thread.Sleep(3000);
} static void DoOnError(Task t)
{
Console.WriteLine("task {0} had an error!", t.Id);
Console.WriteLine("my id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
} static void ParentAndChild()
{
Task parent = new Task(ParentTask);
parent.Start();
Thread.Sleep(2000);
Console.WriteLine(parent.Status);
Thread.Sleep(4000);
Console.WriteLine(parent.Status); }
static void ParentTask()
{
Console.WriteLine("task id {0}", Task.CurrentId);
Task child = new Task(ChildTask); // , TaskCreationOptions.DetachedFromParent);
child.Start();
Thread.Sleep(1000);
Console.WriteLine("parent started child");
// Thread.Sleep(3000);
}
static void ChildTask()
{
// Console.WriteLine("task id {0}, parent: {1}", Task.Current.Id, Task.Current.Parent.Id);
Console.WriteLine("child");
Thread.Sleep(5000);
Console.WriteLine("child finished");
} static void TaskMethod()
{
Console.WriteLine("running in a task");
Console.WriteLine("Task id: {0} {1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
} static void ParallelDemo()
{
// Parallel.For(0, 5, i => Console.WriteLine(i));
Parallel.For<string>(0, 20, () => "abcd",
(x, ls, str) =>
{
Console.WriteLine(x);
return "defg";
},
(str) =>
{
Console.WriteLine("action {0}", str);
}); ParallelOptions po = new ParallelOptions(); } //static void ParentAndChild()
//{
// TaskFactory factory = new TaskFactory();
// var t1 = factory.StartNew(() =>
// {
// Console.WriteLine("parent task {0}", Task.CurrentId); // factory.StartNew(() =>
// {
// Console.WriteLine("child task {0}", Task.CurrentId);
// Thread.Sleep(2000);
// Console.WriteLine("finished child");
// }, TaskCreationOptions.AttachedToParent); // Console.WriteLine("finished parent");
// }); // t1.Wait(); //} }
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Wrox.ProCSharp.Threading
{
class Program
{
static void Main()
{
//ParallelFor();
//ParallelForeach();
ParallelInvoke();
} static void ParallelInvoke()
{
//并行运行多个任务:Parallel.Invoke()方法允许传递一个Action委托数组,其中指定应运行的方法
Parallel.Invoke(Foo, Bar);
} static void Foo()
{
Console.WriteLine("foo");
} static void Bar()
{
Console.WriteLine("bar");
} static void ParallelForeach()
{
string[] data = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"}; //异步方式遍历
ParallelLoopResult result =
Parallel.ForEach<string>(data, s =>
{
Console.WriteLine(s);
}); Parallel.ForEach<string>(data,
(s, pls, l) =>
{
Console.WriteLine("{0} {1}", s, l); }); } static void ParallelFor()
{
//ParallelLoopResult result =
// Parallel.For(0, 10, i =>
// {
// Console.WriteLine("{0}, task: {1}, thread: {2}", i,
// Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
// Thread.Sleep(10); // });
//Console.WriteLine(result.IsCompleted); //ParallelLoopResult result =
// Parallel.For(10, 40, (int i, ParallelLoopState pls) =>
// {
// Console.WriteLine("i: {0} task {1}", i, Task.CurrentId);
// Thread.Sleep(10);
// if (i > 15)
// pls.Break();
// });
//Console.WriteLine(result.IsCompleted);
//Console.WriteLine("lowest break iteration: {0}", result.LowestBreakIteration); Parallel.For<string>(0, 20,
() =>
{
// invoked once for each thread
Console.WriteLine("init thread {0}, task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
return String.Format("t{0}", Thread.CurrentThread.ManagedThreadId);
},
(i, pls, str1) =>
{
// invoked for each member
Console.WriteLine("body i {0} str1 {1} thread {2} task {3}", i, str1,
Thread.CurrentThread.ManagedThreadId,
Task.CurrentId);
Thread.Sleep(10);
return String.Format("i {0}", i); },
(str1) =>
{
// final action on each thread
Console.WriteLine("finally {0}", str1);
}); }
}
}

运行结果:

代码实例:

  

  

  

ps:在运行书中附带的sample时,报错:

经查证,发现这是由于StartupUri中的内容与窗口名称不一致所导致。

这部分的知识可以参考一篇译文:WPF教程(十)使用App.xaml

C#读书笔记:线程,任务和同步的更多相关文章

  1. 读书笔记—CLR via C#同步构造28-29章节

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  2. 【读书笔记】iOS网络-同步请求,队列式异步请求,异步请求的区别

    一,同步请求的最佳实践. 1,只在后台过程中使用同步请求,除非确定访问的是本地文件资源,否则请不要在主线程上使用. 2,只有在知道返回的数据不会超出应用的内存时才使用同步请求.记住,整个响应体都会位于 ...

  3. 【读书笔记】iOS-网络-同步请求,队列式异步请求,异步请求的区别

    一,同步请求的最佳实践. 1,只在后台过程中使用同步请求,除非确定访问的是本地文件资源,否则请不要在主线程上使用. 2,只有在知道返回的数据不会超出应用的内存时才使用同步请求.记住,整个响应体都会位于 ...

  4. Clr Via C#读书笔记---线程基础

    趣闻:我是一个线程:http://kb.cnblogs.com/page/542462/ 进程与线程 进程:应用程序的一个实例使用的资源的集合.每个进程都被赋予了一个虚拟地址空间. 线程:对CPU进行 ...

  5. OCA读书笔记(9) - 管理数据同步

    9.Managing Data Concurrency 描述锁机制以及oracle如何管理数据一致性监控和解决锁冲突 管理数据的并发--管理锁数据的不一致:脏读更改丢失幻影读 脏读:数据是指事务T2修 ...

  6. Java并发读书笔记:线程安全与互斥同步

    目录 导致线程不安全的原因 什么是线程安全 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 互斥同步实现线程安全 synchronized内置锁 锁即对象 是否要释放锁 实现原理 啥是重进入? ...

  7. <<操作系统精髓与设计原理>>读书笔记(一) 并发性:互斥与同步(1)

    <<操作系统精髓与设计原理>>读书笔记(一) 并发性:互斥与同步 并发问题是所有问题的基础,也是操作系统设计的基础.并发包括很多设计问题,其中有进程间通信,资源共享与竞争,多个 ...

  8. 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化

    <深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...

  9. windows线程池四种情形(win核心读书笔记)

    windows线程池四种情形(win核心读书笔记) Mircosoft从Windows2000引入线程池API,并在Vista后对线程池重新构架,引入新的线程池API.以下所有线程池函数均适用于Vis ...

  10. 副本机制与副本同步------《Designing Data-Intensive Applications》读书笔记6

    进入到第五章了,来到了分布式系统之中最核心与复杂的内容:副本与一致性.通常分布式系统会通过网络连接的多台机器上保存相同数据的副本,所以在本篇之中,我们来展开看看如何去管理和维护这些副本,以及这个过程之 ...

随机推荐

  1. go语言中如何模拟100个IP同时并发访问服务器,每个ip要重复访问1000次。每个Ip一分钟之内只能访问一次

    package main import ( "time" "sync" "fmt" "sync/atomic" ) ty ...

  2. UVA690-Pipeline Scheduling(dfs+二进制压缩状态)

    Problem UVA690-Pipeline Scheduling Accept:142  Submit:1905 Time Limit: 3000 mSec  Problem Descriptio ...

  3. 如何征服面试官,拿到Offer [转]

    转自 https://my.oschina.net/cccyb/blog/3012768 又到了茶余饭后的时间,想想写点什么,掐指一算,噢呦,快到3月份了,职场的金三银四跳槽季又来了,不同的是今年比往 ...

  4. 使用dd备份和恢复ASM中的数据文件头

    这里用大家随处可见的(除了extent分布的x$kffxp需要百度和google外),其余都是文档中有详细记载的常用ASM视图来实现同样功能: 下面的用于从ASM中备份数据文件头: SQL> s ...

  5. MongoDB非关系型数据库开发手册

    一:NoSql数据库 什么是NoSQL? NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称. NoSQL用于超 ...

  6. 讲一个关于paxos的故事...

    先讲一个故事. 从前,在国王Leslie Lamport的统治下,有个黑暗的希腊城邦叫paxos.城邦里有3类人, 决策者 提议者 群众 虽然这是一个黑暗的城邦但是很民主,按照议会民主制的政治模式制订 ...

  7. 跨域访问-需要设置HTTP响应标头

    前提:服务端网站的配置(被请求的网站) 1.需要在IIS服务器站点的功能视图中设置HTTP响应标头: 2.双击“HTTP响应标头”进入设置界面 3.点击右侧添加按钮弹出窗口 4.填入需要设置的信息 名 ...

  8. 【Java面试宝典】深入理解JAVA虚拟机

    一.运行时数据区域 线程隔离:线程隔离的意思,就是给不同的线程多分配的资源用,以做到不争用. 线程共享:线程共享就是资源只有一个没有办法分配更多,只能共享. Java虚拟机管理的内存包括几个运行时数据 ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试

    1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...

  10. POJ - 3244-Difference between Triplets

    其实我最开始没有这道题...是做到UPC-11079-小P的决斗,训练结束后然后搜索了一波,才了解这个题的. 非常牛逼的题...这么多人做出来了...我好菜... 对于每对三元组Ta=(La,Ja,K ...