我这里针对现有的C#多线程技术进行一个汇总,一是复习,二是方便索引,文章部份知识点来源于网络,非本人原创。
一、并行(异步):
1.System.Threading.Tasks命名空间下的(TPL):
1.1:Parallel.Invoke --并行执行多个任务,主线程等待并行执行完毕后才开始续续运行。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static
void
Main(
string
[] args)
{
Parallel.Invoke(
new
ParallelOptions() { MaxDegreeOfParallelism=2},Run1,Run2);
Console.WriteLine(
"我是主线程!"
);
Console.Read();
}
static
void
Run1()
{
Console.WriteLine(
"我是任务一,我运行3s"
);
Thread.Sleep(3000);
Console.WriteLine(
"任务一执先完成"
);
}
static
void
Run2()
{
Console.WriteLine(
"我是任务二,我运行5s"
);
Thread.Sleep(5000);
Console.WriteLine(
"任务二执先完成"
);
}
|
1.2:Parallel.For--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。
示例:
1
2
3
4
5
|
Parallel.For(0, 10, (i) => {
Console.WriteLine(
"我是第{0}个任务,线程ID是:{1}"
,i,Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(
new
Random().Next(10) * 10 * 500);
Console.WriteLine(
"线程ID是:{0}执行完成"
, Thread.CurrentThread.ManagedThreadId);
});
|
1.3:Parallel.ForEach--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。注意它有多个重载方法
示例:
1
2
3
4
5
6
7
8
9
10
11
|
var
bag =
new
ConcurrentBag<
int
>();
Parallel.ForEach(Partitioner.Create(0, 100), i =>
{
for
(
int
m = i.Item1; m < i.Item2; m++)
{
bag.Add(m);
Console.WriteLine(
"我是第{0}个任务,线程ID是:{1}"
, m, Thread.CurrentThread.ManagedThreadId);
}
});
Console.WriteLine(
"并行计算:集合有:{0}"
, bag.Count);
|
1.4:TAP(基于任务的异步编),使用Task类 (注意:默认任务开启后,会在新线程中执行,主线程不会等待任务而是继续下面的执行,若使用Task.WaitAll,则会等待相应的任务完成后才会执行)
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//第一种方式启动
var
task1 =
new
Task(() =>
//实例化
{
Run1();
});
task1.Start();
//启动
//第二种方式开启
var
task2 = Task.Factory.StartNew(() =>
//直接创建任务并启动
{
Run2();
});
//主线程等待任务执行完
Task.WaitAll(task1, task2);
|
2.ParallelEnumerable类中的扩展方法(先将枚举对象使用AsParallel转换成ParallelQuery类型,然后就可以使用ParallelQuery在ParallelEnumerable类相关的扩展方法)
示例:
1
2
|
var
resultList = testList.AsParallel().Where(i=>i>=100).ToList();
Console.WriteLine(
"resultList Count:{0}"
, resultList.Count);
|
3.创建新Thread--新线程启动后,主线程与创建的线程各自执行,若需要主线程等待异步线程执行完成后才执行,则应使用asyncThread.Join方法。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
static
void
AsyncThreadMethod()
{
Console.WriteLine(
"我是异步执行线程,线程ID是:{0}"
, Thread.CurrentThread.ManagedThreadId);
}
static
void
AsyncThreadMethod(
object
state)
{
Console.WriteLine(
"我是异步执行线程,线程ID是:{0},状态:{1}"
, Thread.CurrentThread.ManagedThreadId,state);
}
//创建线程并执行
Thread asyncThread =
new
Thread(
new
ThreadStart(AsyncThreadMethod));
asyncThread.IsBackground =
true
;
asyncThread.Start();
Thread asyncThread2 =
new
Thread(
new
ParameterizedThreadStart(AsyncThreadMethod));
asyncThread2.IsBackground =
true
;
asyncThread2.Start(
"这是来自主线程的参数"
);
|
4.使用ThreadPool.QueueUserWorkItem静态方法--WaitCallback回调方法要求其必需带一个object的参数
示例:
1
2
3
|
ThreadPool.QueueUserWorkItem(
new
WaitCallback(AsyncThreadMethod));
//不带参数,则系统将state自动设为null
ThreadPool.QueueUserWorkItem(
new
WaitCallback(AsyncThreadMethod),
"这是来自主线程的参数"
);
|
5.APM(异步编程模型),利用BeginInvoke与EndInvoke完成异步执行委托方法
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
Func<
string
,
string
> funcDelegate = (s) =>
{
Console.WriteLine(
"我是Func委托方法!"
);
return
"委托方法参数:"
+ s;
};
//1.无阻塞异步回调
var
aysncResult = funcDelegate.BeginInvoke(
"这是来自主线程的参数"
,
new
AsyncCallback((result) =>
{
//获取委托对象,调用EndInvoke方法获取运行结果
AsyncResult _result = (AsyncResult)result;
var
func = (Func<
string
,
string
>)_result.AsyncDelegate;
string
data = func.EndInvoke(_result);
Console.WriteLine(data +
",附加参数:"
+ _result.AsyncState.ToString());
}),
"其它参数"
);
//2.阻塞主线程,使主线程等待执行完毕
string
data2 =
null
;
var
aysncResult2 = funcDelegate.BeginInvoke(
"这是来自主线程的参数2"
,
null
,
null
);
data2 = funcDelegate.EndInvoke(aysncResult2);
//第一种阻塞方法
while
(!aysncResult2.IsCompleted)
//第二种阻塞方法
{
Thread.Sleep(200);
//虚拟操作
Console.WriteLine(
"主线程等待..."
);
}
data2 = funcDelegate.EndInvoke(aysncResult2);
WaitHandle[] waitHandles =
new
WaitHandle[]{ aysncResult2.AsyncWaitHandle };
while
(WaitHandle.WaitAll(waitHandles, 5000))
//第三种阻塞方法
{
Console.WriteLine(
"主线程等待..."
);
}
|
6. EAP(基于事件的异步编程)--主要用在客户端应用程序中
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//例子一
var
client =
new
WebClient();
client.DownloadProgressChanged +=
delegate
(
object
s, DownloadProgressChangedEventArgs e)
{
Console.WriteLine(
"Download Percent:{0}"
, e.ProgressPercentage);
};
client.DownloadStringCompleted +=
delegate
(
object
s,DownloadStringCompletedEventArgs e){
Console.WriteLine(
"Download Content Length:{0}"
,e.Result.Length);
Console.WriteLine(
"Download Completed!"
);
};
client.DownloadStringAsync(
new
Uri(
"http://www.zuowenjun.cn"
));
//例子二
BackgroundWorker worker =
new
BackgroundWorker();
worker.DoWork += (s, e) => {
Console.WriteLine(
"异步执行中。。。"
);
};
worker.RunWorkerCompleted += (s, e) => {
Console.WriteLine(
"异步执行完成。。。"
);
};
worker.RunWorkerAsync();
|
7.async和await关键字
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
Task<
double
> GetValueAsync(
double
num1,
double
num2)
{
return
Task.Run(() =>
{
for
(
int
i = 0; i < 1000000; i++)
{
num1 = num1 / num2;
}
return
num1;
});
}
public
async
void
DisplayValue()
{
double
result = await GetValueAsync(1234.5, 1.01);
//此处会开新线程处理GetValueAsync任务,然后方法马上返回
//这之后的所有代码都会被封装成委托,在GetValueAsync任务完成时调用
System.Diagnostics.Debug.WriteLine(
"Value is : "
+ result);
}
//调用
DisplayValue();
//不会阻塞主线程
|
参考以下相关文章:
本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4900468.html ,如需转载请自行联系原作者