C#中级-常用多线程操作(持续更新)

一、前言

     四线程操作向来是编制程序的常用操作,精通好宗旨的操作可以让程序运营的尤为实惠。本文不求大而全,只是将小编要好干活儿中时时使用的四线程操作做个分类和小结。平日纪念力倒霉的时候仍是能够看看。本文参照他事他说加以考察了多篇园子里的优质博文,在篇章最终会贴出具体来源,感激他们的无私贡献。

 

二、关于线程

(1) 为什么使用线程:

     
能够利用线程将代码同任何代码隔断,提升应用程序的可信赖性;

      能够行使线程来简化编码;

      可以使用线程来兑现产出实施。

(2)
进程、应用程序域以及线程的涉嫌:

     
进度(Process)是Windows系统中的三个基本概念,它包括着一个运作程序所要求的财富。进度之间是周旋独立的,一个历程不可能访谈另贰个进度的数目(除非接纳遍布式总括格局),四个进程运营的败诉也不会潜濡默化别的进度的运作,Windows系统正是使用进度把专门的事业划分为多少个单身的区域的。进程能够驾驭为三个程序的主干边界。

     
应用程序域(AppDomain)是三个程序运转的逻辑区域,它能够算得一个轻量级的进度,.NET的次序集便是在利用程序域中运作的,二个历程能够分包有多少个利用程序域,二个运用程序域也足以包罗多少个程序集。在贰个行使程序域中隐含了二个或七个上下文context,使用前后文CLLacrosse就可见把某个特殊指标的图景放置在分裂容器其中。

     
线程(Thread)是经过中的基本进行单元,在进程入口实行的首先个线程被视为那一个进度的主线程。

     
关系图如下:

图片 1

三、Thread

     Thread恐怕是除了Task之外用的最多的四线程类。一般用法:

// one thread
Thread thread = new ThreadStart(functiion);
thread.Start();

// thread.join
Thread ThreadA = new Thread(delegate()
{
  //do something      
});
  
Thread ThreadB = new Thread(delegate()
{       
  //do something;  
  
      ThreadA.Join();
  
  //do another thing      
});
  
//启动线程
ThreadA.Start();
ThreadB.Start();

//一开始,两个线程相互交替运行,当线程B运行到线程A的join时,会先让线程A执行完,然后线程B再继续执行。你可以理解为超车,一开始两者互不相让,当join时,线程A超车了线程B

 

四、ThreadPool

       
由于线程的开创和销毁需求消耗一定的付出,过多的施用线程会导致内部存款和储蓄器财富的稀疏,出于对质量的思虑,于是引进了线程池的定义。线程池维护多个伸手队列,线程池的代码从队列提取职务,然后委派给线程池的一个线程实践,线程实施完不会被立时销毁,那样不仅能够在后台实施义务,又有啥不可减小线程创建和销毁所带来的开拓。

      
如若二个线程的岁月不短,就没须要用线程池了(不是不能够作长日子操作,而是不宜。),而且大家还不可能调整线程池中线程的初叶、挂起、和间断。

ThreadPool.QueueUserWorkItem(function,parameter);

 

五、Task

     Task是作者用的最多的二十八线程形式,一般接纳的秘技如下:  

// one task
var task = new Task(() =>{
    // do something
});
task.Start();

// task one by one 
var task = new Task(() =>{ 
      // do something   
});

Task task2 =  task.ContinueWith(()=>{
    // do something   
});
task.Start();

// many tasks
var tasks = new Task[PackCount];  //多线程任务

for (int index = 0; index < PackCount; index++)
{
   int Threadindex = index; 
   var task = new Task(() =>
         {
                // do something   }
   });
   tasks[Threadindex] = task;
   task.Start();
}
Task.WaitAll(tasks); //等待所有线程完成
//Task.WaitAny(tasks); //等待一个线程完成继续执行主程序

//Task.Factory
Task.Factory.StartNew(()=>{ // do something }); 

 

六、Invoke、BeginInvoke、DynamicInvoke

     
此处首要表达的是delegate下的各个Invoke

      Invoke
(委托方法施行在调用处同三个线程中)

delegate void MyDelegate();

MyDelegate del = new MyDelegate(Function);
del .Invoke();     //使用到委托的invoke方法

 

    
 BeginInvoke(它从线程池中抓取贰个空暇线程,来寄托执市场价格势)

A景况:使用IAsyncResult.IsCompleted剖断子线程是还是不是施行实现

delegate T MyDelegate();

MyDelegate del = new MyDelegate(Function);

IAsyncResult result = del.BeginInvoke(parameter,null,null);

//if the branch thread is not completed
while(!result.IsCompleted)  
{
    // the main thread do another thing
}

T data = del.EndInvoke(result); 
// var data is the result of Function with parameter

 

B意况:使用IAsyncResult.AsyncWaitHandle.WaitOne(timeout)判别子线程是还是不是实践达成

delegate T MyDelegate();

MyDelegate del = new MyDelegate(Function);

IAsyncResult result = del.BeginInvoke(parameter,null,null);

//if the branch thread is not completed
while(!result.AsyncWaitHandle.WaitOne(int timeout))  
{
    // the main thread do another thing
}

T data = del.EndInvoke(result); 
// var data is the result of Function with parameter

 

C情况:使用WaitHandle.WaitAll(WaitHandle[],timeout)剖断子线程是或不是实践完结

delegate T MyDelegate();

MyDelegate del = new MyDelegate(Function);

IAsyncResult result = del.BeginInvoke(parameter,null,null);

WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle,........ };

while (!WaitHandle.WaitAll(waitHandleList,int timeout))
{
    // the main thread do another thing
}

T data = del.EndInvoke(result); 
// var data is the result of Function with parameter

 

D意况:使用轮询形式来检查评定异步方法的情景极度麻烦,並且功能不高,为此要求采纳回调函数。主线程能够欣慰做本人的事,而异步线程实现操作后实施回调函数就能够。回调函数依旧是在异步线程上,而非主线程上。

delegate T MyDelegate();

MyDelegate del = new MyDelegate(Function);

IAsyncResult result = del.BeginInvoke(parameter,new AsyncCallback(callbackFunction),object);

....MainThread do somethng...

static void callbackFunction(IAsyncResult result)
{
     AsyncResult  _result = (AsyncResult )result;

     MyDelegate del = (MyDelegate)_result.AsyncDelegate;

     T data = del.EndInvoke(_result);

     T1 objectReciever = (T1)result.AsyncResult; //object=result.AsyncResult
}

 

        DynamicInvoke:

       与Delegate.Invoke类似,同步,且同线程,独一分裂的是,是采取早先时期绑定的章程来调用委托方法,所以时间代价相当的大。

专门的工作实例:在WPF中出现一种极其:“调用线程无法访问此指标,因为另三个线程拥有该目标。

状态A:若是发生该极度的代码是在xaml.cs文件中,那么Dispatcher.Invoke已经足足了。

动静B:
即便爆发该非常的代码是在.cs文件中,那么在Stack Overflow上有一招:

 1 private void RaiseEventOnUIThread(Delegate theEvent, object[] args)
 2 {
 3       foreach (Delegate d in theEvent.GetInvocationList())
 4       {
 5             ISynchronizeInvoke syncer = d.Target as ISynchronizeInvoke;
 6             if (syncer == null)  //静态函数为null
 7             {
 8                     d.DynamicInvoke(args);
 9             }
10             else
11             {
12                     syncer.BeginInvoke(d, args); //在创建了此对象的线程上异步执行委托
13             }
14        }
15 }

    

References:

【1】http://blog.sina.com.cn/s/blog\_5a6f39cf0100qtzf.html

【2】http://www.cnblogs.com/slikyn/articles/1525940.html

【3】http://kb.cnblogs.com/page/130487/\#t3

【4】http://blog.csdn.net/soft\_123456/article/details/38819877

【5】http://www.cnblogs.com/laoyur/archive/2011/04/14/2016025.html

【6】http://blog.csdn.net/cselmu9/article/details/8274556

【7】http://stackoverflow.com/questions/1698889/raise-events-in-net-on-the-main-ui-thread

相关文章