这里我要强调一个概念,
多线程是多线程,
异步编程是异步编程
这两个是有区别的概念;
我可以说多线程天生就要异步的特点;但你不能说多线程成就等同于我们的异步编程;
根不能说异步编程就是我们的多线程。这里不要搞混淆了;
再net中的进化如下:
多线程:Thread =>ThreadPool=> Task
异步编程:BenginInvokeXXX EndInvokeXXX IAsyncResult=> async await (这里面配合着Task的使用)(基于任务的异步模式 (TAP) 时来使用异步操作)
好接下来,再来总结我们的线程(任务)的等待。
总结:
方法一:Thread.Sleep(),这个要预估,等待的时间应该大于我们的子线程执行的时间。
方法二:当然就是我们最常用的Join() 方法了,堵塞当前调用子线程成的方法,直到我们的子线程执行完毕。
方法二:主线程轮训子线程(这个是基于我们的IasyncResult 编程模式的,及时传说中的beginxxxx endxxxx这种模式)
方法三:采用通知的方法就是我们的EevntWaitHanld = new AutoRestEevnt(false),然后waitOne 和 Set 的方式来进行的,效果非常好滴呀;
方法四:我把它命名为偏方:就是利用独占锁的机制,当子线程用完锁之后,释放,让给我们的主线程,前提是要确保我们的子线程先得到锁;
方法五:这个就是基于我们的Task的wait方法;
这里我给出一些,练习的demo,仅供参考使用;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication13
{
//我们把它叫做等待子线程,或者,等待子线程一定的时间;
//最原始的是使用 waitEevnt的方法;我们甚至可以用 poll的方式;
//还有基于事件编程的回调方式;
public class Person
{
}
class Program
{
//evnet wait handle
//该方法也可以用来进行线程的同步滴呀;
public static object locker = new object();
public static EventWaitHandle handler = new AutoResetEvent(false);
public static void Eat()
{
Thread.Sleep(3000);
}
public static void Eat_WithSet()
{
Thread.Sleep(3000);
handler.Set(); //子线程发出做完实行的信号;
}
public static void Eat_WithLock()
{
Console.WriteLine("枷锁开始");
lock (locker)
{
Thread.Sleep(3000); //假设,我们这里有很多的是事情要做的呀;
//效果非常好;
}
Console.WriteLine("枷锁释放");
}
public static void Eat_Loop()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Console.WriteLine("子");
}
}
//那么这个方法就不能为空了
public static void Eat_Wait()
{
for (int i = 0; i < 10; i++)
{
Task.Delay(1000).Wait();
Console.WriteLine("子");
}
}
public static void TestJoin()
{
Console.WriteLine("main start");
Thread thread = new Thread(Eat);
thread.Start();
//给我等着;
Console.WriteLine("主线程先做点其他事情;");
//这我们我们可以直接用线程自带的方法;
thread.Join();
Console.WriteLine("好了,子线程事情做完了..");
Console.WriteLine("main end");
Console.ReadLine();
}
public static void Test_Set()
{
Console.WriteLine("main start");
Thread thread = new Thread(Eat_WithSet);
thread.Start();
//给我等着;
Console.WriteLine("主线程先做点其他事情;");
handler.WaitOne();
Console.WriteLine("好了,子线程事情做完了..");
Console.WriteLine("main end");
Console.ReadLine();
}
public static void Test11()
{
Console.WriteLine("main start");
Thread thread = new Thread(Eat_WithSet);
thread.Start();
//给我等着;
Console.WriteLine("主线程先做点其他事情;");
handler.WaitOne(TimeSpan.FromSeconds(3));
//注意这里,一点 waitone 和 task.wait 如果都指定了 等待的时间;
//如果子线程在指定的时间内没有做完时间,那么我们就开始了主线程的方法;
//这里并没有真正的取消线程;
//问题又来了,如果去取消子线程呢;这个......
Console.WriteLine("好了,不堵塞,主线程了,");
Console.WriteLine("main end");
Console.ReadLine();
}
//偏方
public static void Test_Lock()
{
Console.WriteLine("main start");
Thread thread = new Thread(Eat_WithLock);
thread.Start();
//给我等着;
Console.WriteLine("主线程先做点其他事情;");
//如果是单线层的话,我还是使用一点偏方;
//那就是我们的lock方法滴呀;
Thread.Sleep(20);//为了让子线程得到锁,我们这里估计sleep一下了
//所以尼玛的叫偏方了;
lock (locker)
{
//当然这种方式,就是完全出去一种四等的状态;
//等待另外一个线程释放锁;
Console.WriteLine("这个表示我们的另外一个线程执行完毕了;");
}
Console.ReadLine();
}
//如果要取消原来的方法的话,还得到原来的的方法去操作,整的是麻烦的一件事情;
//不过有我们的Task 就方便多;;
public static void Test_Task()
{
//task的取消就相对简单的多了;
Console.WriteLine("main start");
Task task = Task.Run(()=>Eat_Wait());
Console.WriteLine("mian do something.then wait task");
// task.Wait(); //默认情况下,它会等待task执行完毕;
task.Wait(TimeSpan.FromSeconds(3));//在这里只能等待三秒,三秒只有,就不堵塞我们的主线程;
//这里这的注意的事情是,等待不等于取消哦;
//这一点是相对非常关键的啦;
//先一节我们再来略略线程的取消啦滴呀;
Console.WriteLine("task completed...");
Console.WriteLine("main end");
Console.ReadLine();
}
static void Main(string[] args)
{
//Test();
//Test1();
//Test11();
//Test_Lock();
//Test_Task();
}
}
}
//这里我再来演示一个set 之后,通知多个线程的实例,或则理解成为广播是似的传递消息;
或则:多个线程在等待某一个线程的信号;
to do
线程只有不断的去判断他的isalive属性;
异步编程则可以使用的轮训的回调的方式; 如果你的主线程一直等待,那么 尼玛的就叫异步编程了;
public static void Test_IsAlive()
{
//Eat_Loop
Console.WriteLine("main start");
Thread thread = new Thread(Eat_Loop);
thread.Start();
Console.WriteLine("mian do something.then wait task");
while (thread.IsAlive)
{
Thread.Sleep(100);
Console.WriteLine("子线程还在zuoshiser");
}
Console.WriteLine("子线程把事儿做完了!");
Console.WriteLine("mian end");
}
public static int CountInfo(int x)
{
Thread.Sleep(5000);
return x+100;
}
public static void Test_IsComplete()
{
//异步编程了
Func<int, int> fn = CountInfo;
IAsyncResult actionResult = fn.BeginInvoke(100, CountInfoCallback, null); //既没有回调,也没有参数这样的方法不太正常;
while (!actionResult.IsCompleted)
{
Thread.Sleep(100);
Console.WriteLine("子线程还在zuoshiser");
}
//做完之后 记得endinvoke;
int result= fn.EndInvoke(actionResult);
//这样就可以得到我们的结果;
//在这里结束,也可以在回调方法中结束 endInvoek;
}
static void CountInfoCallback(IAsyncResult iar)
{
Console.WriteLine("这里是回调....");
AsyncResult ar = (AsyncResult)iar;
Func<int, int> del = (Func<int, int>)ar.AsyncDelegate;
var result = del.EndInvoke(iar);
//总的的来说,就是我们的采用回调和轮训的两种方式;
//来实现我们的异步编程的实现;
//不过好在,现在我们又了 async 和await 基于task的异步编程;
//那效果,整的是杠杠的,效果是非常好滴呀;
}
好了就到这里;。
转载于:https://www.cnblogs.com/mc67/p/7467550.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)