c# 多线程
多线程
.net 4.0 Task类的出现提高了线程的使用效率
外部变量
int i = 0;
//100以内的随机数
Random r = new Random(100);
Task t = new Task(() =>
{
for (int v = 0; v < 100; v++)
//最大值50
i += r.Next(50);
});
t.Start(); //开始线程
t.Wait(); //等待线程结束
Console.WriteLine("这是执行Task1后等待完成:" + i.ToString());
内部变量
Random r = new Random(DateTime.Now.Second);
//Task<T>直接返回结果
//当调用Result属性时,会自动等待线程结束,等同调用了Wait()。
Task<int> t = new Task<int>(() =>
{
int i = 0;
for (int v = 0; v < 100; v++)
i += r.Next(100);
return i;
});
t.Start(); //开始线程
Console.WriteLine("这是执行Task1后等待完成:" + t.Result.ToString());
ContinueWith
Random r = new Random(DateTime.Now.Second);
Task<int> t = new Task<int>(() =>
{
int i = 0;
for (int v = 0; v < 100;v++ )
i += r.Next(100);
return i;
});
t.ContinueWith((Task<int> task) =>
{
Console.WriteLine("这是执行完毕Task1后继续调用Task2:" + task.Result.ToString());
});
t.Start();
ContinueWith链式写法
Random r = new Random(DateTime.Now.Second);
Task<int> t = new Task<int>(() =>
{
int i = 0;
for (int v = 0; v < 100; v++)
i += r.Next(100);
return i;
});
Task t2 = t.ContinueWith((Task<int> task) =>
{
Console.WriteLine(task.Result.ToString());
});
t2.ContinueWith(task =>
{
Console.WriteLine("这是执行完毕Task1后继续调用Task2,Task2后调用Task。");
});
t.Start();
Task中断
CancellationTokenSource cts = new CancellationTokenSource();
var ctoken = cts.Token;
Task t1 = new Task(() =>
{
for (int v = 0; v < 10; v++)
{
if(ctoken.IsCancellationRequested)
{
//第一种写法
//这个会抛出异常
ctoken.ThrowIfCancellationRequested();
//另一种写法
//这个不会返回异常,但是获取不到是否是中断还是执行完毕。
//return;
}
Thread.Sleep(1000);
Console.WriteLine(v);
}
},ctoken);
t1.Start();
Thread.Sleep(2000);
cts.Cancel();
try
{
t1.Wait();
}
catch
{
if (t1.IsCanceled)
Console.WriteLine("cancel");
}
cts.Dispose();
中途取消Task执行,Token
一是正常结束、二是产生例外、三是透过Cancel机制,这三种情况都会反映在Task.Status属性上
值 说明
Created Task已经建立,但未呼叫Start。
WaitingForActivation Task已排入排程,但尚未执行(一般我们建立的Task不会有此状态,只有ContinueWith所产生的Task才会有此状态)。
WaitingToRun Task已排入排程,等待执行中。
Running Task执行中。
WaitingForChildrenToComplete Task正等待子Task結束。
RanToCompletion Task已经正常执行完毕。
Canceled Task已被取消。
Faulted Task执行中发生未预期例外。
除了Status属性外,Task还提供了另外三个属性来判定Task状态。
属性 说明
IsCompleted Task已经正常执行完毕。
IsFaulted Task执行中法生未预期例外。
IsCanceled Task已被取消。
StartNew
创建一个新线程,并且直接运行,省略了start的过程
Task<int> t1 = Task.Factory.StartNew<int>(() =>
{
int total = 0;
for (int i = 0; i < 10; i++)
total += i;
Console.WriteLine("线程运行");
Thread.Sleep(12000);
return total;
});
ContinueWhenAny
t1,t2中有任何一个task完成都会触发ContinueWhenAny线程,该线程只执行一次
Task<int> t1 = Task.Factory.StartNew<int>(() =>
{
int total = 0;
for (int i = 0; i < 10; i++)
total += i;
Thread.Sleep(12000);
return total;
});
Task<int> t2 = Task.Factory.StartNew<int>(() =>
{
int total = 0;
for (int i = 10; i < 20; i++)
total += i;
Thread.Sleep(10000);
return total;
});
Task tfinal = Task.Factory.ContinueWhenAny<int>(
new Task<int>[] { t1, t2 }, (Task<int> task) =>
{
if (task.Status == TaskStatus.RanToCompletion)
{
Console.WriteLine(task.Result);
}
});
ContinueWhenAll
t1,t2全部执行完毕之后,会触发ContinueWhenAll线程,该线程只执行一次
Task<int> t1 = Task.Factory.StartNew<int>(() =>
{
int total = 0;
for (int i = 0; i < 10; i++)
total += i;
Thread.Sleep(12000);
return total;
});
Task<int> t2 = Task.Factory.StartNew<int>(() =>
{
int total = 0;
for (int i = 10; i < 20; i++)
total += i;
Thread.Sleep(10000);
return total;
});
Task tfinal = Task.Factory.ContinueWhenAll(
new Task<int>[] { t1, t2 },(Task<int>[] taskCollection) =>
{
foreach (var task in taskCollection)
{
Console.WriteLine(task.Result);
}
});