net 中多线程有几种实现方法?

如题所述

第1个回答  2022-12-11
1:UI线程。这个线程是操作系统自动创建的,你画了个winform,那么程序一启动,自然有了这么个线程。值得注意的是,你添加一个Timer控件,现实的多线程,实际上,依然在UI线程里。只是定时被Timer夺去控制权而已,本质上依然是单线程。另一个线索也可以论证:本来非UI线程想更新UI界面,是需要利用delegate,involk等来实现的,但是在timer控件的线程里,是不需要的。\x0d\x0a2:Thread thread = new Thread(obj.functionName); thread.start();\x0d\x0a这样自定义的线程是真正的多线程,它的使用也是最灵活的。不像Timer线程,精确度只有50ms。值得注意的是:如果需要启动的线程函数是带输入参数的,怎么办?\x0d\x0a有两个办法:\x0d\x0aA:你不是启动obj对象里的函数吗?在thread.start();之前,你先添加这句话 MyObject obj = new MyObject(int a ,int b); 这样,obj.functionName函数里可以直接使用a和b了。还有个方法,就是利用委托封装函数,然后thread.start(参数);具体代码如下:\x0d\x0a\x0d\x0a[ComVisibleAttribute(false)]\x0d\x0apublic delegate void ParameterizedThreadStart(Object obj)\x0d\x0a//这个Thread类的构造方法的定义如下:\x0d\x0apublic Thread(ParameterizedThreadStart start);\x0d\x0a\x0d\x0apublic static void myStaticParamThreadMethod(Object obj)\x0d\x0a{\x0d\x0a Console.WriteLine(obj);\x0d\x0a}\x0d\x0a \x0d\x0astatic void Main(string[] args)\x0d\x0a{\x0d\x0a Thread thread = new Thread(myStaticParamThreadMethod);\x0d\x0a thread.Start("通过委托的参数传值");\x0d\x0a}\x0d\x0a\x0d\x0a3:利用threadpool线程池技术。threadpool的主要原理是池里面的线程不会完成一个任务就消亡,而是会继续执行其他的任务,这减少了线程的消亡和生成的代价。\x0d\x0a主要是ThreadPool.QueueUserWorkItem()和ThreadPool.RegisterWaitForSingleObject(···)两个静态函数。具体如下:\x0d\x0aQueueUserWorkItem的使用:\x0d\x0astatic void ThreadProc(Object stateInfo)\x0d\x0a {\x0d\x0a Console.WriteLine("Hello from the thread pool.");\x0d\x0a }\x0d\x0aMain函数里ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc)); 即可。(注意WaitCallback系统委托),它的功能就像第2种方法里提到的new thread。\x0d\x0a那么RegisterWaitForSingleObject是干什么的呢?这个方法的做用是向线程池添加一个可以定时执行的方法。有点像第一种方法里提到的timer线程,却不属于UI线程。\x0d\x0a具体的使用如下:\x0d\x0aAutoResetEvent wait = new AutoResetEvent(false);\x0d\x0aobject state = new object();\x0d\x0aThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(test), state, 5000, false);\x0d\x0a//5000是间隔调用的时间,也就是wait变量卡住的timeout时间(我觉得内部是这样实现的)\x0d\x0await.Set(); //如果有set这句话,那么第一次执行不用等5秒,则直接执行目标函数,否则没这句话,第一次执行要等5秒的。\x0d\x0a还有一个要注意:我平常使用的是ManualResetEvent,但在threadpool里,首先要选的是AutoResetEvent,因为AutoResetEvent能自动reset,所以下一次间隔来了,又要重新等待5秒钟,达到定时器的目的。如果是ManualResetEvent,要么一次执行不了(初始值为false),要么不间断的玩命执行。\x0d\x0aManualResetEvent和AutoResetEvent的另一个重要区别是前者能一次唤醒多个线程,而后者一次只能唤醒一个线程。\x0d\x0a其实RegisterWaitForSingleObject函数的使用有点想我封装好的MyTimer类的实现了:我里面的while死循环里用了个wait.waitone(2000,false);即可。\x0d\x0a对了,说到这里,RegisterWaitForSingleObject函数实现的定时器,如果手动停止呢?\x0d\x0a这要用到Unregister函数:\x0d\x0aRegisteredWaitHandle rw = ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(test), state, 3000, false);\x0d\x0arw.Unregister(wait);\x0d\x0a\x0d\x0a嗯讨论了这么多线程的东西,干脆再说一个小点:Thread.IsBackground=true的时候,指示该线程为后台线程。后台线程将会随着主线程的退出而退出
相似回答