先来一个局部变量的问题
如下面代码
for (int i = 0; i < 10; i++)
{
Task.Run(new Action(() => {
Console.WriteLine(i);
}));
}
看到上面代码 本以为 输出会是0-9 结果看下面
这是因为是异步,所以i++并没有等待Task.Run的执行,所以i在一直++下去 就变成了10
可以用下面代码来解决上面问题
for (int i = 0; i < 10; i++)
{
string value = i.ToString();
Task.Run(new Action(() => {
Console.WriteLine(value);
}));
}
用一个新的局部变量来存上i的值 就可以实现输出正确的值了
异常处理
这里就不演示了,直接说明,对于多线程的异常处理,不能包在最外面,这样会抓不到异常,因为在还没有报异常的时候,主线程就已经执行完了,应该直接把Try catch紧紧的包裹着Task的外面
如
for (int i = 0; i < 5; i++)
{
string value = i.ToString();
Task.Run(new Action(() =>
{
try
{
if (value == "3")
{
throw new Exception("错误");
}
Console.WriteLine("执行成功,线程ID为{0}", Thread.CurrentThread.ManagedThreadId);
}
catch (Exception)
{
Console.WriteLine("有一个执行失败");
throw;
}
}));
}
线程取消
CancellationTokenSource cts = new CancellationTokenSource();
for (int i = 0; i < 50; i++)
{
string value = i.ToString();
Task.Run(new Action(() =>
{
try
{
if (value == "3")
{
throw new Exception("错误");
}
Thread.Sleep(200);
if (!cts.IsCancellationRequested)//IsCancellationRequested 被取消
{
Console.WriteLine("{0} 执行成功", Thread.CurrentThread.ManagedThreadId);
}
else
{
Console.WriteLine("{0} 被取消", Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception)
{
cts.Cancel();
Console.WriteLine("有一个执行失败");
throw;
}
}));
}
注意:在上面代码中,StartNew来启动一个线程的时候。可以通过传递cts.Token参数的方式,来让线程执行前就判断是否已经取消
结果