namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int a = 0;
Task task = Task.Run(() => dowork(
ref a));
Console.WriteLine(a);
}
static void dowork(ref int a)
{
a = 2;
Console.WriteLine(a);
}
}
}
为什么输出是0,2不是2,2
{
class Program
{
static void Main(string[] args)
{
int a = 0;
Task task = Task.Run(() => dowork(
ref a));
Console.WriteLine(a);
}
static void dowork(ref int a)
{
a = 2;
Console.WriteLine(a);
}
}
}
为什么输出是0,2不是2,2
Task task = Task.Run(() => dowork(
ref a));
Console.WriteLine(a);
主线程开出task任务后,马上去执行下一句Console.WriteLine(a);不管task线程了,task自己执行自己的顺序:
static void Main(string[] args)
{
1、int a = 0;
2、Task task = Task.Run(() => dowork(
ref a));
3、 Console.WriteLine(a);
}
static void dowork(ref int a)
{
a = 2;
4、Console.WriteLine(a);
}
Task执行不阻塞主线程
要严格控制执行顺序,需要使用信号量或者其他的同步方法
很简单,这样写代码 static void Main(string[] args)
{
int a = 0;
dowork(ref a);
Console.WriteLine(a);
}
static void dowork(ref int a)
{
a = 2;
Console.WriteLine(a);
}不要自己明明是并发多线程操作,又来问“怎么产生不并发多线程的结果”。那就是为了 Task 而 Task 地写代码,多此一举了。
{
class Program
{
static void Main(string[] args)
{
int a = 0;
Task task = Task.Run(() => dowork(
ref a));
task.Wait();
Console.WriteLine(a);
}
static void dowork(ref int a)
{
a = 2;
Console.WriteLine(a);
}
}
}
https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx 不仅要会用,更要知道什么情况下可以用。
所以输出0或者2都是可能的。
因为主线程和task是并发执行的。
至于是不是要让任务执行先输出,可以wait
Task task = Task.Run(() => dowork(
ref a));
for(i=0;i<100;i++) //你要故意让外面比线程运行的慢,那么他就是2,2
{
}
Console.WriteLine(a);
用ContinueWith
如果你想全部运行完再运行某个东西的话。用whenAll
如果要输出2,那么就需要主线程来等待子线程执行完成后再执行下面的Console.WriteLine(a),方法是task.Wait();
这样main方法中的代码就改为如下:
int a = 0;
Task task = Task.Run(() => dowork( ref a));
task.Wait();//等待任务完成再执行下面的代码,如果不加这一句,那么下面的代码将在任务完前就执行了。
Console.WriteLine(a);总结一下就是:Task.Run 中的方法开启了新的线程,并且在主线程中不特别指定等待它完成的情况下,主线程是不会被阻塞(所以叫异步),而在task.Wait();方法明确指定主线程需要子线程完程后才执行后面代码的情况下,这时就变成了同步。
总体来说,多线程确实是比较绕的,这源于计算机工作原理的博大精深。刚开始学习时我自己把异步、同步和同时的概念总是分不清楚。初步理解的话可以认为异步就是同时进行任务,谁也不等谁,而同步是我们没有多线程时学习的,它反而是不同时,就是后面的代码一定要等前面的代码执行完才执行。