整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          C#多線程

          .概念

          進(jìn)程,線程,應(yīng)用程序的定義網(wǎng)上有很多資料,但是有些抽象。通俗的來講,進(jìn)程就是 一旦一個(gè)應(yīng)用程序開始運(yùn)行,那么這個(gè)應(yīng)用程序就會(huì)存在一個(gè)屬于這個(gè)應(yīng)用程序的進(jìn)程。線程就是進(jìn)程中的基本執(zhí)行單元,每個(gè)進(jìn)程中都至少存在著一個(gè)線程,這個(gè)線程是根據(jù)進(jìn)程創(chuàng)建而創(chuàng)建的,所以這個(gè)線程我們稱之為主線程。那么多線程就是包含有除了主線程之外的其他線程。如果一個(gè)線程可以執(zhí)行一個(gè)任務(wù),那么多線程就是可以同時(shí)執(zhí)行多個(gè)任務(wù)。

          2.C# 中的線程

          Thread 類,Thread 類是用于控制線程的基礎(chǔ)類,它存在于 System.Threading 命名空間。通過 Thread 可以控制當(dāng)前應(yīng)用程序域中線程的創(chuàng)建、掛起、停止、銷毀。

          Thread 一些常用屬性:

          Thread 一些常用屬性

          Thread 一些常用方法:

          Thread 一些常用方法

          Thread 的優(yōu)先級(jí):

          Thread 的優(yōu)先級(jí)

          3.多線程的基本示例

          3.1 創(chuàng)建線程

          創(chuàng)建一個(gè)控制臺(tái)應(yīng)用程序,

          namespace MultiThreadDemo
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      ThreadDemoClass demoClass = new ThreadDemoClass();      
                      /////如下兩種方法都可以創(chuàng)建線程,二選一即可
                      /////////////////創(chuàng)建線程 方法1  S
                      ////通過類方法直接創(chuàng)建線程
                      //Thread thread = new Thread(demoClass.Run);
                      /////////////////創(chuàng)建線程 方法1  E
          
                      ///////////////創(chuàng)建線程 方法2  S
                      //創(chuàng)建一個(gè)委托,并把要執(zhí)行的方法作為參數(shù)傳遞給這個(gè)委托
                      ThreadStart threadStart = new ThreadStart(demoClass.Run);
                      Thread thread = new Thread(threadStart);
                      ///////////////創(chuàng)建線程 方法2  E
          
                      //設(shè)置為后臺(tái)線程
                      thread.IsBackground = true;
                      //開始線程
                      thread.Start();
                      ////等待直到線程完成
                      //thread.Join();
          
                      Console.WriteLine("Main thread working...");
                      Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
          
                      Console.ReadKey();
                  }    
              }
          
          		public class ThreadDemoClass
          		{
          				public void Run()
          				{
          						Console.WriteLine("Child thread working...");
          						Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
          				}
          		}
          }

          運(yùn)行結(jié)果:

          說明:

          1)主線程創(chuàng)建了一個(gè)子線程并啟動(dòng)了它,但是主線程沒有等到子線程執(zhí)行完成,而是繼續(xù)再往下執(zhí)行的------線程異步或同步

          2)如果要等子線程執(zhí)行完成后再執(zhí)行主線程-----通過線程的join()方法,方法不難,不單獨(dú)展開

          3)上面創(chuàng)建進(jìn)程的方法沒有帶參數(shù)和返回值------參考3.2節(jié)

          4)thread.IsBackground = true,即把當(dāng)前線程設(shè)置為后臺(tái)線程,因?yàn)槭褂?thread.Start() 啟動(dòng)的線程默認(rèn)為前臺(tái)線程。區(qū)別:前臺(tái)線程就是系統(tǒng)會(huì)等待所有的前臺(tái)線程運(yùn)行結(jié)束后,應(yīng)用程序域才會(huì)自動(dòng)卸載。而設(shè)置為后臺(tái)線程之后,應(yīng)用程序域會(huì)在主線程執(zhí)行完成時(shí)被卸載,而不會(huì)等待異步線程的執(zhí)行完成。

          3.2 創(chuàng)建帶參數(shù)和返回值的線程

          上面的這種使用多線程的方式只是簡(jiǎn)單的輸出一段內(nèi)容而已,多數(shù)情況下我們需要對(duì)線程調(diào)用的方法傳入?yún)?shù)和接收返回值的,但是上面這種方法是不接受參數(shù)并且沒有返回值的,那么我們可以使用 ParameterizedThreadStart 委托來創(chuàng)建多線程,這個(gè)委托可以接受一個(gè) object 類型的參數(shù),我們可以在這上面做文章,看如下示例,

          3.2.1 一個(gè)參數(shù)

          參考如下示例代碼,

          namespace MultiThreadDemo
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      
                      ThreadParameterDemoClass demoClass = new ThreadParameterDemoClass();
                      //創(chuàng)建一個(gè)委托,并把要執(zhí)行的方法作為參數(shù)傳遞給這個(gè)委托
                      ParameterizedThreadStart threadStart = new ParameterizedThreadStart(demoClass.Run);
                      //創(chuàng)建一個(gè)新的線程
                      Thread thread = new Thread(threadStart);
          
                      //開始線程,并傳入?yún)?shù)
                      thread.Start("shufac");
          
                      Console.WriteLine("Main thread working...");
                      Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                      Console.ReadKey();
          
                  }
              }
              
              public class ThreadParameterDemoClass
              {
                  public void Run(object obj)
                  {
                      string name = obj as string;
          
                      Console.WriteLine("Child thread working...");
                      Console.WriteLine("My name is " + name);
                      Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  }
              }
          }

          運(yùn)行結(jié)果:

          從上面的運(yùn)行結(jié)果可以看到在多線程實(shí)現(xiàn)了參數(shù)的傳遞,可是它也只有一個(gè)參數(shù),并且它接受的參數(shù)是 object 類型的(萬類之源),也就是說既可以是值類型或引用類型,也可以是自定義類型。(當(dāng)然,自定義類型其實(shí)也是屬于引用類型的)下面我們使用自定義類型作為參數(shù)傳遞。

          3.2.2 自定義類型參數(shù)傳遞

          參考如下示例代碼:

          namespace MultiThreadDemo
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      ThreadSelfDefParameterDemoClass demoClass = new ThreadSelfDefParameterDemoClass();
          
                      //創(chuàng)建一個(gè)委托,并把要執(zhí)行的方法作為參數(shù)傳遞給這個(gè)委托
                      ParameterizedThreadStart threadStart = new ParameterizedThreadStart(demoClass.Run);
          
                      //創(chuàng)建一個(gè)新的線程
                      Thread thread = new Thread(threadStart);
          
                      UserInfo userInfo = new UserInfo();
                      userInfo.Name = "shufac";
                      userInfo.Age = 30;
          
                      //開始線程,并傳入?yún)?shù)
                      thread.Start(userInfo);
          
                      Console.WriteLine("Main thread working...");
                      Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                      Console.ReadKey();
                  }
          
              }
              
              public class ThreadSelfDefParameterDemoClass
              {
                  public void Run(object obj)
                  {
                      UserInfo userInfo = (UserInfo)obj;
          
                      Console.WriteLine("Child thread working...");
                      Console.WriteLine("My name is " + userInfo.Name);
                      Console.WriteLine("I'm " + userInfo.Age + " years old this year");
                      Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  }
              }
          
              public class UserInfo
              {
                  public string Name { get; set; }
          
                  public int Age { get; set; }
              }
          
          
          }
          

          運(yùn)行結(jié)果:

          3.2.3 帶參數(shù)和返回值的線程

          可以使用成員變量來試試 獲取線程的返回值,參考如下示例代碼,

          class Program
          {
              List<UserInfo> userInfoList = new List<UserInfo>();
          
              static void Main(string[] args)
              {
                  Program program = new Program();
          
                  ParameterizedThreadStart threadStart = new ParameterizedThreadStart(program.Run);
                  Thread thread = null;
                  UserInfo userInfo = null;
          
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
          
                      thread = new Thread(threadStart);
                      thread.Start(userInfo);
                      thread.Join();
                  }
          
                  foreach (UserInfo user in program.userInfoList)
                  {
                      Console.WriteLine("My name is " + user.Name);
                      Console.WriteLine("I'm " + user.Age + " years old this year");
                      Console.WriteLine("Thread ID is:" + user.ThreadId);
                  }
                  
                  Console.ReadKey();
              }
          
              public void Run(object obj)
              {
                  UserInfo userInfo = (UserInfo)obj;
          
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
                  userInfoList.Add(userInfo);
              }
          }

          運(yùn)行結(jié)果:

          用上面這種方法勉強(qiáng)可以滿足返回值的需求,但是卻有很大的局限性,因?yàn)檫@里我使用的是成員變量,所以也就限制了線程調(diào)用的方法必須是在同一個(gè)類里面。

          所以也就有了下面的方法,使用委托異步調(diào)用的方法(參考第3.4節(jié)------異步委托)。

          小結(jié):

          1)傳一個(gè)參數(shù)的方法,任何內(nèi)置類型的數(shù)據(jù)應(yīng)該都是可以的

          2)使用自定義類型作為參數(shù)傳遞,理論上更多個(gè)參數(shù)也都是可以實(shí)現(xiàn)的

          3)使用 ThreadStart 和 ParameterizedThreadStart 創(chuàng)建線程還是比較簡(jiǎn)單的,但是由于線程的創(chuàng)建和銷毀需要耗費(fèi)一定的開銷,過多地使用線程反而會(huì)造成內(nèi)存資源的浪費(fèi),從而影響性能,出于對(duì)性能的考慮,于是引入了線程池的概念。

          3.3線程池

          線程池并不是在 CLR 初始化的時(shí)候立刻創(chuàng)建線程的,而是在應(yīng)用程序要?jiǎng)?chuàng)建線程來執(zhí)行任務(wù)的時(shí)候,線程池才會(huì)初始化一個(gè)線程,初始化的線程和其他線程一樣,但是在線程完成任務(wù)之后不會(huì)自行銷毀,而是以掛起的狀態(tài)回到線程池。當(dāng)應(yīng)用程序再次向線程池發(fā)出請(qǐng)求的時(shí)候,線程池里掛起的線程會(huì)再度激活執(zhí)行任務(wù)。這樣做可以減少線程創(chuàng)建和銷毀所帶來的開銷。線程池建立的線程默認(rèn)為后臺(tái)線程。

          示例代碼:

          namespace MultiThreadDemo
          {
              class Program
              {
                  static void Main(string[] args)
                  {
          
                      ThreadPoolDemoClass demoClass = new ThreadPoolDemoClass();
          
                      //設(shè)置當(dāng)沒有請(qǐng)求時(shí)線程池維護(hù)的空閑線程數(shù)
                      //第一個(gè)參數(shù)為輔助線程數(shù)
                      //第二個(gè)參數(shù)為異步 I/O 線程數(shù)
                      ThreadPool.SetMinThreads(5, 5);
          
                      //設(shè)置同時(shí)處于活動(dòng)狀態(tài)的線程池的線程數(shù),所有大于次數(shù)目的請(qǐng)求將保持排隊(duì)狀態(tài),直到線程池變?yōu)榭捎?            //第一個(gè)參數(shù)為輔助線程數(shù)
                      //第二個(gè)參數(shù)為異步 I/O 線程數(shù)
                      ThreadPool.SetMaxThreads(100, 100);
          
                      //使用委托綁定線程池要執(zhí)行的方法(無參數(shù))
                      WaitCallback waitCallback1 = new WaitCallback(demoClass.Run1);
                      //將方法排入隊(duì)列,在線程池變?yōu)榭捎脮r(shí)執(zhí)行
                      ThreadPool.QueueUserWorkItem(waitCallback1);
          
          
                      //使用委托綁定線程池要執(zhí)行的方法(有參數(shù))
                      WaitCallback waitCallback2 = new WaitCallback(demoClass.Run1);
                      //將方法排入隊(duì)列,在線程池變?yōu)榭捎脮r(shí)執(zhí)行
                      ThreadPool.QueueUserWorkItem(waitCallback2, "Brambling");
          
          
                      UserInfo userInfo = new UserInfo();
                      userInfo.Name = "Brambling";
                      userInfo.Age = 33;
          
                      //使用委托綁定線程池要執(zhí)行的方法(有參數(shù),自定義類型的參數(shù))
                      WaitCallback waitCallback3 = new WaitCallback(demoClass.Run2);
                      //將方法排入隊(duì)列,在線程池變?yōu)榭捎脮r(shí)執(zhí)行
                      ThreadPool.QueueUserWorkItem(waitCallback3, userInfo);
          
                      Console.WriteLine();
                      Console.WriteLine("Main thread working...");
                      Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                      Console.ReadKey();
          
                  }
              }
              
              public class ThreadPoolDemoClass
              {
                  public void Run1(object obj)
                  {
                      string name = obj as string;
          
                      Console.WriteLine();
                      Console.WriteLine("Child thread working...");
                      Console.WriteLine("My name is " + name);
                      Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  }
          
                  public void Run2(object obj)
                  {
                      UserInfo userInfo = (UserInfo)obj;
          
                      Console.WriteLine();
                      Console.WriteLine("Child thread working...");
                      Console.WriteLine("My name is " + userInfo.Name);
                      Console.WriteLine("I'm " + userInfo.Age + " years old this year");
                      Console.WriteLine("Child thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  }
              }
          
              public class UserInfo
              {
                  public string Name { get; set; }
          
                  public int Age { get; set; }
              }
          
          }

          運(yùn)行結(jié)果:

          使用線程池建立的線程也可以選擇傳遞參數(shù)或不傳遞參數(shù),并且參數(shù)也可以是值類型或引用類型(包括自定義類型)。看上面的結(jié)果發(fā)現(xiàn)了什么?沒錯(cuò),第一次執(zhí)行的方法的線程ID為4,最后一次執(zhí)行的方法的線程ID也為4。這就說明第一次請(qǐng)求線程池的時(shí)候,線程池建立了一個(gè)線程,當(dāng)它執(zhí)行完成之后就以掛起狀態(tài)回到了線程池,在最后一次請(qǐng)求的時(shí)候,再次喚醒了該線程執(zhí)行任務(wù)。這樣就很容易理解了。

          小結(jié):線程池的引入主要解決頻繁創(chuàng)建線程造成的內(nèi)存資源的浪費(fèi),是個(gè)輔助功能,特殊的應(yīng)用場(chǎng)景比較有用,用于提升性能。

          3.4 異步委托

          委托的異步調(diào)用有兩個(gè)比較重要的方法:BeginInvoke() 和 EndInvoke()。

          3.4.1 異步委托完成參數(shù)傳遞示例

          參考如下示例代碼:

          class Program
          {
              //定義一個(gè)委托類
              private delegate UserInfo MyDelegate(UserInfo userInfo);
          
              static void Main(string[] args)
              {
                  ThreadDemoClass demoClass = new ThreadDemoClass();
                  List<UserInfo> userInfoList = new List<UserInfo>();
                  UserInfo userInfo = null;
                  UserInfo userInfoRes = null;
          
                  //創(chuàng)建一個(gè)委托并綁定方法
                  MyDelegate myDelegate = new MyDelegate(demoClass.Run);
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
                      //傳入?yún)?shù)并執(zhí)行異步委托
                      IAsyncResult result = myDelegate.BeginInvoke(userInfo,null,null);
                      //異步操作是否完成
                      while (!result.IsCompleted)
                      {
                          Thread.Sleep(100);
                          Console.WriteLine("Main thread working...");
                          Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                          Console.WriteLine();
                      }
                      //結(jié)束異步委托,并獲取返回值
                      userInfoRes = myDelegate.EndInvoke(result);
                      userInfoList.Add(userInfoRes);
                  }
          
                  foreach (UserInfo user in userInfoList)
                  {
                      Console.WriteLine("My name is " + user.Name);
                      Console.WriteLine("I'm " + user.Age + " years old this year");
                      Console.WriteLine("Thread ID is:" + user.ThreadId);
                  }
                  
                  Console.ReadKey();
              }
          }
          
          public class ThreadDemoClass
          {
              public UserInfo Run(UserInfo userInfo)
              {
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
          
                  Console.WriteLine("Child thread working...");
                  Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
                  Console.WriteLine();
          
                  return userInfo;
              }
          }

          執(zhí)行結(jié)果:

          BeginInvoke() 方法用于異步委托的執(zhí)行開始,EndInvoke() 方法用于結(jié)束異步委托,并獲取異步委托執(zhí)行完成后的返回值。IAsyncResult.IsCompleted 用于監(jiān)視異步委托的執(zhí)行狀態(tài)(true / false),這里的時(shí)間是不定的,也就是說一定要等到異步委托執(zhí)行完成之后,這個(gè)屬性才會(huì)返回 true。如果異步委托的方法耗時(shí)較長(zhǎng),那么主線程會(huì)一直工作下去。BeginInvoke() 是可以接受多個(gè)參數(shù)的,它的參數(shù)個(gè)數(shù)和參數(shù)類型取決于定義委托時(shí)的參數(shù)個(gè)數(shù)和類型,無論它有多少個(gè)參數(shù),最后兩個(gè)參數(shù)都是不變的,下面我們會(huì)說到。

          3.4.2異步委托自定義指定單個(gè)線程等待時(shí)間

          我們還可以用下面的方法 WaitOne(),自定義一個(gè)等待的時(shí)間,如果在這個(gè)等待時(shí)間內(nèi)異步委托沒有執(zhí)行完成,那么就會(huì)執(zhí)行 while 里面的主線程的邏輯,反之就不會(huì)執(zhí)行。

          class Program
          {
              //定義一個(gè)委托類
              private delegate UserInfo MyDelegate(UserInfo userInfo);
          
          
              static void Main(string[] args)
              {
                  ThreadDemoClass demoClass = new ThreadDemoClass();
                  List<UserInfo> userInfoList = new List<UserInfo>();
                  UserInfo userInfo = null;
                  UserInfo userInfoRes = null;
          
                  //創(chuàng)建一個(gè)委托并綁定方法
                  MyDelegate myDelegate = new MyDelegate(demoClass.Run);
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
          
                      //傳入?yún)?shù)并執(zhí)行異步委托
                      IAsyncResult result = myDelegate.BeginInvoke(userInfo,null,null);
          
                      //阻止當(dāng)前線程,直到 WaitHandle 收到信號(hào),參數(shù)為指定等待的毫秒數(shù)
                      while (!result.AsyncWaitHandle.WaitOne(1000))
                      {
                          Console.WriteLine("Main thread working...");
                          Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                          Console.WriteLine();
                      }
          
                      //結(jié)束異步委托,并獲取返回值
                      userInfoRes = myDelegate.EndInvoke(result);
          
                      userInfoList.Add(userInfoRes);
                  }
          
                  foreach (UserInfo user in userInfoList)
                  {
                      Console.WriteLine("My name is " + user.Name);
                      Console.WriteLine("I'm " + user.Age + " years old this year");
                      Console.WriteLine("Thread ID is:" + user.ThreadId);
                  }
                  
                  Console.ReadKey();
              }
          }
          
          public class ThreadDemoClass
          {
              public UserInfo Run(UserInfo userInfo)
              {
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
          
                  Console.WriteLine("Child thread working...");
                  Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
                  Console.WriteLine();
          
                  return userInfo;
              }
          }

          運(yùn)行結(jié)果:

          WaitOne() 方法只能用于監(jiān)視當(dāng)前線程的對(duì)象,如果要監(jiān)視多個(gè)對(duì)象可以使用 WaitAny(WaitHandle[], int)或 WaitAll (WaitHandle[] , int) 這兩個(gè)方法。

          3.4.3異步委托自定義指定多個(gè)線程等待時(shí)間

          WaitOne() 方法只能用于監(jiān)視當(dāng)前線程的對(duì)象,如果要監(jiān)視多個(gè)對(duì)象可以使用 WaitAny(WaitHandle[], int)或 WaitAll (WaitHandle[] , int) 這兩個(gè)方法。

          參考如下示例代碼,

          class Program
          {
              //定義一個(gè)委托類
              private delegate UserInfo MyDelegate(UserInfo userInfo);
          
              static void Main(string[] args)
              {
                  ThreadDemoClass demoClass = new ThreadDemoClass();
                  List<UserInfo> userInfoList = new List<UserInfo>();
                  UserInfo userInfo = null;
                  UserInfo userInfoRes = null;
          
                  //創(chuàng)建一個(gè)委托并綁定方法
                  MyDelegate myDelegate = new MyDelegate(demoClass.Run);
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
          
                      //傳入?yún)?shù)并執(zhí)行異步委托
                      IAsyncResult result = myDelegate.BeginInvoke(userInfo,null,null);
                      IAsyncResult result1 = myDelegate.BeginInvoke(userInfo, null, null);
          
                      //定義要監(jiān)視的對(duì)象,不能包含對(duì)同一對(duì)象的多個(gè)引用
                      WaitHandle[] waitHandles = new WaitHandle[] { result.AsyncWaitHandle, result1.AsyncWaitHandle };
                      while (!WaitHandle.WaitAll(waitHandles,1000))
                      {
                          Console.WriteLine("Main thread working...");
                          Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                          Console.WriteLine();
                      }
          
                      //結(jié)束異步委托,并獲取返回值
                      userInfoRes = myDelegate.EndInvoke(result);
                      userInfoList.Add(userInfoRes);
          
                      userInfoRes = myDelegate.EndInvoke(result1);
                      userInfoList.Add(userInfoRes);
                  }
          
                  foreach (UserInfo user in userInfoList)
                  {
                      Console.WriteLine("My name is " + user.Name);
                      Console.WriteLine("I'm " + user.Age + " years old this year");
                      Console.WriteLine("Thread ID is:" + user.ThreadId);
                  }
                  
                  Console.ReadKey();
              }
          }
          
          public class ThreadDemoClass
          {
              public UserInfo Run(UserInfo userInfo)
              {
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
          
                  Console.WriteLine("Child thread working...");
                  Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
                  Console.WriteLine();
          
                  return userInfo;
              }
          }
          

          運(yùn)行結(jié)果:

          WaitAll() 方法和 WaitAny() 方法都可以監(jiān)視多個(gè)對(duì)象,不同的是 WaitAll() 方法需要等待所有的監(jiān)視對(duì)象都收到信號(hào)之后才會(huì)返回 true,否則返回 false。而 WaitAny() 則是當(dāng)有一個(gè)監(jiān)視對(duì)象收到信號(hào)之后就會(huì)返回一個(gè) int 值,這個(gè) int 值代表的是當(dāng)前收到信號(hào)的監(jiān)視對(duì)象的索引。注意:在定義監(jiān)視對(duì)象的時(shí)候,不能包含對(duì)同一個(gè)對(duì)象的多個(gè)引用,我這里是定義的兩個(gè)示例,所以是不同的對(duì)象。

          接下來我們看上面的執(zhí)行結(jié)果。為什么主線程沒有“工作”呢?這里你可以在異步委托調(diào)用的 Run() 方法里面為線程設(shè)置一個(gè)幾秒鐘或者更長(zhǎng)地掛起時(shí)間。然后在設(shè)置監(jiān)視對(duì)象這里設(shè)置一個(gè)小于線程掛起的時(shí)間,然后調(diào)試你就能發(fā)現(xiàn)問題的所在了。其實(shí)也不算是問題,只是之前的理解有誤。

          其實(shí) WaitAll() 方法和 WaitAny() 方法設(shè)置監(jiān)視對(duì)象,然后指定一個(gè)時(shí)間(毫秒值),這里的意思是當(dāng)所有的監(jiān)視對(duì)象在指定的時(shí)間內(nèi)都接收到信號(hào)時(shí)(這里是指 WaitAll() 方法),就不會(huì)執(zhí)行 while 里面的主線程的工作,反之就會(huì)執(zhí)行。

          這里你可能會(huì)有疑問,如果是這樣,那我把前面的邏輯非運(yùn)算符去掉那不就相反了么。這么理解邏輯上是沒錯(cuò)的,但是我還是要說的是,盡量不要去嘗試,因?yàn)檫@會(huì)是個(gè)死循環(huán)。WaitAny() 這個(gè)方法也是一樣的理解,不同的是,它不需要等到所有的監(jiān)視對(duì)象都收到信號(hào),它只需要一個(gè)監(jiān)視對(duì)象收到信號(hào)就夠了,這里就不在演示了。

          上面的方法可以看出,我們雖然使用的是異步的方式調(diào)用的方法,但是依舊需要等待異步的方法返回執(zhí)行的結(jié)果,盡管我們可以不阻塞主線程,但是還是覺得不太方便。所以也就有了本篇博客最后一個(gè)要點(diǎn),異步委托的回調(diào)函數(shù)。

          3.4.4異步委托回調(diào)函數(shù)

          示例代碼如下,

          class Program
          {
              //定義一個(gè)委托類
              private delegate UserInfo MyDelegate(UserInfo userInfo);static void Main(string[] args)
              {
                  ThreadDemoClass demoClass = new ThreadDemoClass();
                  UserInfo userInfo = null;
          
                  //創(chuàng)建一個(gè)委托并綁定方法
                  MyDelegate myDelegate = new MyDelegate(demoClass.Run);
          
                  //創(chuàng)建一個(gè)回調(diào)函數(shù)的委托
                  AsyncCallback asyncCallback = new AsyncCallback(Complete);
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
          
                      //傳入?yún)?shù)并執(zhí)行異步委托,并設(shè)置回調(diào)函數(shù)
                      IAsyncResult result = myDelegate.BeginInvoke(userInfo, asyncCallback, null);
                  }
          
                  Console.WriteLine("Main thread working...");
                  Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  Console.WriteLine();
                  
                  Console.ReadKey();
              }
          
              public static void Complete(IAsyncResult result)
              {
                  UserInfo userInfoRes = null;
          
                  AsyncResult asyncResult = (AsyncResult)result;
          
                  //獲取在其上調(diào)用異步調(diào)用的委托對(duì)象
                  MyDelegate myDelegate = (MyDelegate)asyncResult.AsyncDelegate;
                  
                  //結(jié)束在其上調(diào)用的異步委托,并獲取返回值
                  userInfoRes = myDelegate.EndInvoke(result);
          
                  Console.WriteLine("My name is " + userInfoRes.Name);
                  Console.WriteLine("I'm " + userInfoRes.Age + " years old this year");
                  Console.WriteLine("Thread ID is:" + userInfoRes.ThreadId);
              }
          }
          
          public class ThreadDemoClass
          {
              public UserInfo Run(UserInfo userInfo)
              {
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
          
                  Console.WriteLine("Child thread working...");
                  Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
                  Console.WriteLine();
          
                  return userInfo;
              }
          }

          運(yùn)行結(jié)果:

          從上面可以看到主線程再執(zhí)行了異步委托之后繼續(xù)執(zhí)行了下去,然后在回調(diào)函數(shù)里輸出了信息,也就是說在調(diào)用了異步委托之后就不管了,把之后的結(jié)束委托和獲取委托的返回值放到了回調(diào)函數(shù)中,因?yàn)榛卣{(diào)函數(shù)是沒有返回值的,但是回調(diào)函數(shù)可以有一個(gè)參數(shù)。上面說到的 BeginInvoke() 方法的最后兩個(gè)參數(shù),它的倒數(shù)第二個(gè)參數(shù)就是一個(gè)回調(diào)函數(shù)的委托,最后一個(gè)參數(shù)可以設(shè)置傳入回調(diào)函數(shù)的參數(shù)。如下:

          class Program
          {
              //定義一個(gè)委托類
              private delegate UserInfo MyDelegate(UserInfo userInfo);
          
              static List<UserInfo> userInfoList = new List<UserInfo>();
          
              static void Main(string[] args)
              {
                  ThreadDemoClass demoClass = new ThreadDemoClass();
                  UserInfo userInfo = null;
          
                  //創(chuàng)建一個(gè)委托并綁定方法
                  MyDelegate myDelegate = new MyDelegate(demoClass.Run);
          
                  //創(chuàng)建一個(gè)回調(diào)函數(shù)的委托
                  AsyncCallback asyncCallback = new AsyncCallback(Complete);
          
                  //回調(diào)函數(shù)的參數(shù)
                  string str = "I'm the parameter of the callback function!";
          
                  for (int i = 0; i < 3; i++)
                  {
                      userInfo = new UserInfo();
                      userInfo.Name = "Brambling" + i.ToString();
                      userInfo.Age = 33 + i;
          
                      //傳入?yún)?shù)并執(zhí)行異步委托,并設(shè)置回調(diào)函數(shù)
                      IAsyncResult result = myDelegate.BeginInvoke(userInfo, asyncCallback, str);
                  }
          
                  Console.WriteLine("Main thread working...");
                  Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());
                  Console.WriteLine();
                  
                  Console.ReadKey();
              }
          
              public static void Complete(IAsyncResult result)
              {
                  UserInfo userInfoRes = null;
          
                  AsyncResult asyncResult = (AsyncResult)result;
          
                  //獲取在其上調(diào)用異步調(diào)用的委托對(duì)象
                  MyDelegate myDelegate = (MyDelegate)asyncResult.AsyncDelegate;
                  
                  //結(jié)束在其上調(diào)用的異步委托,并獲取返回值
                  userInfoRes = myDelegate.EndInvoke(result);
          
                  Console.WriteLine("My name is " + userInfoRes.Name);
                  Console.WriteLine("I'm " + userInfoRes.Age + " years old this year");
                  Console.WriteLine("Thread ID is:" + userInfoRes.ThreadId);
          
                  //獲取回調(diào)函數(shù)的參數(shù)
                  string str = result.AsyncState as string;
                  Console.WriteLine(str);
              }
          }
          
          public class ThreadDemoClass
          {
              public UserInfo Run(UserInfo userInfo)
              {
                  userInfo.ThreadId = Thread.CurrentThread.ManagedThreadId;
          
                  Console.WriteLine("Child thread working...");
                  Console.WriteLine("Child thread ID is:" + userInfo.ThreadId);
                  Console.WriteLine();
          
                  return userInfo;
              }
          }

          運(yùn)行結(jié)果:

          回調(diào)函數(shù)的參數(shù)也是 object 類型的,我這里用的是一個(gè) string 類型,但是它也可以是自定義類型的參數(shù)。

          本篇博客到此結(jié)束,在寫這篇博客的同時(shí)也讓我個(gè)人對(duì)多線程編程加深了理解,多線程編程的知識(shí)點(diǎn)還有很多,后面再繼續(xù)與大家分享。

          參考:

          1)http://www.cnblogs.com/leslies2/archive/2012/02/07/2310495.html#t1

          2)https://www.cnblogs.com/Brambling/p/7144015.html

          言:

          在python里面,數(shù)據(jù)可視化是python的一個(gè)亮點(diǎn)。在python里面,數(shù)據(jù)可視可以達(dá)到什么樣的效果,這當(dāng)然與我們使用的庫(kù)有關(guān)。python常常需要導(dǎo)入庫(kù),并不斷調(diào)用方法,就很像一條流數(shù)據(jù)可視化的庫(kù),有很多,很多都可以后續(xù)開發(fā),然后我們調(diào)用。了解過pyecharts美觀的可視化界面 ,將pyecharts和matplotlib相對(duì)比一下。

          pyecharts和matplotlib的區(qū)別在哪里呢?Matplotlib是Python數(shù)據(jù)可視化庫(kù)的泰斗,盡管已有十多年的歷史,但仍然是Python社區(qū)中使用最廣泛的繪圖庫(kù),它的設(shè)計(jì)與MATLAB非常相似,提供了一整套和MATLAB相似的命令A(yù)PI,適合交互式制圖,還可以將它作為繪圖控件,嵌入其它應(yīng)用程序中。
          Pyecharts是一款將Python與Echarts相結(jié)合的數(shù)據(jù)可視化工具,可以高度靈活的配置,輕松搭配出精美的視圖。其中Echarts是百度開源的一個(gè)數(shù)據(jù)可視化庫(kù),而Pyecharts將Echarts與Python進(jìn)行有機(jī)對(duì)接,方便在Python中直接生成各種美觀的圖形。

          數(shù)據(jù)可視化之matplotlib繪制正余弦曲線圖

          我們先來看最終的實(shí)現(xiàn)效果


          上面這個(gè)圖是最終保存的圖片查看效果
          我們一步一步來實(shí)現(xiàn)
          1:首先我們需要導(dǎo)入基本的庫(kù)
          matplotlib numpy
          matplotlib 是我們本章需要的庫(kù)
          numpy 是我們數(shù)據(jù)分析處理的常見庫(kù),在機(jī)器學(xué)習(xí)時(shí)也會(huì)經(jīng)常用到。

          一步一步來了
          下面展示一些
          內(nèi)聯(lián)代碼片

          第一步

          #1:用到的方法及參數(shù)
          # linspace(start, stop, num=50, endpoint=True, 
          # retstep=False, dtype=None)
          # 相關(guān)參數(shù)的說明
          # 指定在start到stop均分?jǐn)?shù)值
          # start:不可省略
          # stop:有時(shí)包含有時(shí)不包含,根據(jù)endpoint來選擇,默認(rèn)包含
          # num:指定均分的數(shù)量,默認(rèn)為50
          # endpoint:布爾值,可選,默認(rèn)為True。包含stop就True,不包含就# False
          # retstep : 布爾值,可選,默認(rèn)為False。如果為True,返回值和步長(zhǎng)
          # dtype : 輸出數(shù)據(jù)類型,可選。如果不指定,則根據(jù)前面參數(shù)的數(shù)據(jù)類型
          # 2:np.plot(x,y.color.lw,label,ls,mk,mec,mfc)
          # 其中X由所有輸入點(diǎn)坐標(biāo)的x值組成,Y是由與X中包含的x對(duì)應(yīng)的y所組
          # 成的向量
          # color 指定線條的顏色
          # lw指定線條的寬度
          # lw指定線條的樣式,默認(rèn)為實(shí)現(xiàn)
          # mk可以指定數(shù)據(jù)標(biāo)識(shí)符
          # ms可以指定標(biāo)識(shí)符的大小
          # mec可以指定標(biāo)識(shí)符的邊界色彩
          # mfc標(biāo)識(shí)符內(nèi)部填充顏色
          
          import matplotlib.pyplot as plt
          import numpy as np
          #用于正常顯示中文標(biāo)簽
          plt.rcParams['font.sans-serif']=['SimHei']
          # 用于正常顯示符號(hào)
          plt.rcParams['axes.unicode_minus']=False
          x = np.linspace(-np.pi,np.pi,256,endpoint = 256)
          sin,cos = np.sin(x),np.cos(x)
          #繪制,并設(shè)置相關(guān)的參數(shù),這里標(biāo)簽還不會(huì)顯示出來,因?yàn)檫€沒有
          #添加圖例,具體往下面看
          plt.plot(x,sin,color = 'blue',lw=2.5,label = '正弦sin',mec='red')
          plt.plot(x,cos,color = 'red',lw = 2.5,label = '余弦cos()')
          plt.show() #顯示

          第二步

          #用到的方法及參數(shù)
          # plt.xlim(xmin, xmax)
          # xmin:x軸上的最小值
          # xmax:x軸上的最大值
          #plt.ylim() 與上一樣的道理
          #具體如何使用,可以看下面的實(shí)例代碼
          plt.xlim(x.min()*1.5,x.max()*1.5) #將x軸拉伸1.5倍
          plt.ylim(cos.min()*1.5,cos.max()*1.5) # 將y軸拉伸1.5倍
          plt.show()

          第三步

          #用到的方法與參數(shù)
          # plt.xticks([],[])
          # plt.yticks([],[])
          # plt.title('',color,color,..) #設(shè)置標(biāo)題,里面的相關(guān)參數(shù)可以# 指定
          # plt.text(備注內(nèi)容x軸的坐標(biāo),備注內(nèi)容y軸的坐標(biāo) ,'備注內(nèi)容',fontsize,color,..) #給右下角添加備注
          
          #想說的說這里面有連個(gè)參數(shù),分別以列表的形式展示。
          現(xiàn)在只需要介紹是用來設(shè)置坐標(biāo)刻度的。其中第二個(gè)參數(shù)列表
          是用來轉(zhuǎn)義的。具體實(shí)例如下。

          下面展示一些 內(nèi)聯(lián)代碼片

          在x軸的刻度上,我們需要我們需要按照規(guī)則的正余弦刻度來,而不是簡(jiǎn)單的實(shí)數(shù),我們需要圓周率。因此在plt.xticks([],[])的第二個(gè)列表參數(shù)上需要轉(zhuǎn)義。

          #這里的r’$代表開始,$代表結(jié)尾,\代表轉(zhuǎn)義,\pi代表圓周率的意思,r代表原始字符串。因此可以一一對(duì)應(yīng)下來的。

          plt.xticks([-np.pi,-np.pi/2,0,np.pi/2,np.pi],
          [r'$-\pi$',r'$-\pi/2$',r'$0$',r'$\pi/2$',r'$\pi$'])
          plt.yticks([-1,0,1])
          plt.title("繪圖正余弦函數(shù)曲線圖",fontsize = 16,color ='green')
          #給圖片右下角添加備注標(biāo)簽
          plt.text(+2.2,-1.4,"by:jgdabc",fontsize=16,color = 'purple')
          plt.show()

          第四步:

           用到的方法及參數(shù):
            plt.gca()#這個(gè)方法有點(diǎn)東西。
            我要簡(jiǎn)單的去理解,Python庫(kù)太繁雜了。有點(diǎn)頭大。
             plt.gca(),可以獲得axes對(duì)象
            什么又是axes對(duì)象?
           在matplotlib中,整個(gè)圖表為一個(gè)figure對(duì)象。每個(gè)figure
           對(duì)象中可以包含一個(gè)或多個(gè)axes,而axes為坐標(biāo)軸。每個(gè)axes
           對(duì)象都是一個(gè)擁有自己坐標(biāo)系統(tǒng)的繪圖區(qū)域。我們可以理解為通
           過這個(gè)方法我們可以獲得axes對(duì)象,而通過這個(gè)對(duì)象可以幫助我們
           方便的操作坐標(biāo)軸,ok。具體操作看實(shí)例吧!
          
          #我相信能看懂英文的不看注釋也可以看懂
          ax = plt.gca() #獲取Axes對(duì)象
          ax.spines['right'].set_color('none') #隱藏右邊界
          ax.spines['top'].set_color('none')#隱藏上邊界
          ax.xaxis.set_ticks_position('bottom') #x軸坐標(biāo)刻度設(shè)置在坐標(biāo)下面
          ax.spines['bottom'].set_position(('data',0))#將x坐標(biāo)軸平移經(jīng)過(0,0)的位置
          ax.yaxis.set_ticks_position('left')#將y軸坐標(biāo)刻度設(shè)置在坐標(biāo)軸左側(cè)
          ax.spines['left'].set_position(('data',0))#將y軸坐標(biāo)軸平移到(0,0)位置
          plt.show()

          兄弟們是不是有點(diǎn)像了,還不夠。

          第五步:

          用到的方法及參數(shù):
          plt.legend()
          添加圖例
          這樣才會(huì)把我上述label的內(nèi)容顯示出來。
          
          plt.legend(loc ='upper left',fontsize=12)
          plt.show()

          第六步
          注意第六步我們要描點(diǎn),并畫線

          用到的方法及參數(shù)
          plt.plot() # 這個(gè)前面已經(jīng)有說明,不再贅述,這里我們
          要加一個(gè)參數(shù)linewidth指定,將其變?yōu)樘摼€
          plt.scatter() #用來繪制兩個(gè)點(diǎn)的位置
          plt.annotate #用來添加注釋文字,具體解釋我們?cè)趯?shí)例代碼中說明
          
          ```javascript
          t1 = 2*np.pi/3 #取一個(gè)x軸坐標(biāo)點(diǎn)
          t2 = -np.pi # 取第二個(gè)坐標(biāo)點(diǎn)
          #根據(jù)畫線,第一個(gè)列表是x軸坐標(biāo)值,第二個(gè)列表是y軸坐標(biāo)值
          plt.plot([t1,t1],[0,np.sin(t1)],color = 'b',linewidth = 1.5,linestyle = '--')
          #畫線
          plt.plot([t2,t2],[0,np.cos(t2)],color ='r',linewidth=1.5,linestyle="--")
          #標(biāo)注兩個(gè)點(diǎn)的位置(繪制散點(diǎn)圖的方法)
          plt.scatter([t1,],[np.sin(t1),],50,color = 'b') #50為指定的大小
          #為圖表添加注釋
          plt.scatter([t2,],[np.cos(2),],50,color = 'r')
          plt.annotate( r'$\sin(\frac{2\pi}{3}=\frac{\sqrt{3}}{2}$)',
                        xy = (t1,np.sin(t1)), #點(diǎn)的位置
                        xycoords = 'data', #注釋文字的偏移量
                        xytext = (+10,+30), #文字離點(diǎn)的橫縱距離
                        textcoords = 'offset points',
                        fontsize =14,#注釋的大小
                        arrowprops = dict(arrowstyle = '->',connectionstyle = 'arc3,rad=.2')#箭頭指向的彎曲度
          
          
          )
          plt.annotate(r'$\cos(-\pi)=-1$',
                       xy = (t2,np.cos(t2)),
                       xycoords = 'data', #注釋文字的偏移量
                       xytext = (0 ,-40), # 文字離點(diǎn)的橫縱距離
                       textcoords = 'offset points',
                       fontsize = 14,#注釋的大小
                       arrowprops = dict(arrowstyle = '->',connectionstyle='arc3,rad=.2')
          
                       ) #點(diǎn)的位置
          
          plt.show()

          第七步:我想設(shè)置一下x軸和y軸的字體,一提到軸,就用ax.
          我們直接上代碼去解釋

          #遍歷獲取x軸和y軸的刻度,并設(shè)置字體
          for label in ax.get_xticklabels() + ax.get_yticklabels() :
              label.set_fontsize(18)
              label.set_bbox(dict(facecolor = 'r',edgecolor='g',alpha=0.5))#alpha代表透明度
          #繪制填充區(qū)域
          plt.fill_between(x,np.abs(x)<0.5,sin,sin>0.5,color='g',alpha =0.8)
          plt.fill_between(x,cos,where = (-2.5<x)&(x<-0.5),color = 'purple')
          plt.grid() #繪制網(wǎng)格線
          
          plt.savefig("D:\python學(xué)習(xí)數(shù)據(jù)可視化matplot學(xué)習(xí).png",dpi = 300)保存圖片
          plt.show()
          


          注意這里保存一定要先保存,后show。

          最終效果

          給大家完整代碼

          
          import matplotlib.pyplot as plt
          import numpy as np
          plt.rcParams['font.sans-serif']=['SimHei']
          plt.rcParams['axes.unicode_minus']=False
          x = np.linspace(-np.pi,np.pi,256,endpoint=256)
          sin,cos = np.sin(x),np.cos(x)
          plt.plot(x,sin,color = 'blue',lw=2.5,label = '正弦sin',mec='red')
          plt.plot(x,cos,color = 'red',lw = 2.5,label = '余弦cos()')
          plt.xlim(x.min()*1.5,x.max()*1.5)
          plt.ylim(cos.min()*1.5,cos.max()*1.5)
          plt.xticks([-np.pi,-np.pi/2,0,np.pi/2,np.pi],[r'$-\pi$',r'$-\pi/2$',r'$0$',r'$\pi/2$',r'$\pi$'])
          plt.yticks([-1,0,1])
          plt.title("繪圖正余弦函數(shù)曲線圖",fontsize = 16,color ='green')
          plt.text(+2.2,-1.4,"by:jgdabc",fontsize=16,color = 'purple')
          ax = plt.gca()
          ax.spines['right'].set_color('none')
          ax.spines['top'].set_color('none')
          ax.xaxis.set_ticks_position('bottom')
          ax.spines['bottom'].set_position(('data',0))
          ax.yaxis.set_ticks_position('left')
          ax.spines['left'].set_position(('data',0))
          plt.legend(loc ='upper left',fontsize=12)
          t1 = 2*np.pi/3
          t2 = -np.pi
          
          plt.plot([t1,t1],[0,np.sin(t1)],color = 'b',linewidth = 1.5,linestyle = '--')
          
          plt.plot([t2,t2],[0,np.cos(t2)],color ='r',linewidth=1.5,linestyle="--")
          
          plt.scatter([t1,],[np.sin(t1),],50,color = 'b')
          
          plt.scatter([t2,],[np.cos(2),],50,color = 'r')
          plt.annotate( r'$\sin(\frac{2\pi}{3}=\frac{\sqrt{3}}{2}$)',
                        xy = (t1,np.sin(t1)),
                        xycoords = 'data',
                        xytext = (+10,+30),
                        textcoords = 'offset points',
                        fontsize =14,
                        arrowprops = dict(arrowstyle= '->',connectionstyle = 'arc3,rad=.2')#箭頭指向的彎曲度
          
          
          )
          plt.annotate(r'$\cos(-\pi)=-1$',
                       xy = (t2,np.cos(t2)),
                       xycoords = 'data',
                       xytext = (0 ,-40),
                       textcoords = 'offset points',
                       fontsize = 14,
                       arrowprops = dict(arrowstyle = '->',connectionstyle='arc3,rad=.2')
          
                       )
          for label in ax.get_xticklabels() + ax.get_yticklabels() :
              label.set_fontsize(18)
              label.set_bbox(dict(facecolor = 'r',edgecolor='g',alpha=0.5))
          
          plt.fill_between(x,np.abs(x)<0.5,sin,sin>0.5,color='g',alpha =0.8)
          plt.fill_between(x,cos,where = (-2.5<x)&(x<-0.5),color = 'purple')
          plt.grid()
          
          plt.savefig("D:\python學(xué)習(xí)數(shù)據(jù)可視化matplot學(xué)習(xí).png",dpi = 300)
          plt.show()
          


          感謝大家閱讀!!!

          多說一句,很多人學(xué)Python過程中會(huì)遇到各種煩惱問題,沒有人解答容易放棄。小編是一名python開發(fā)工程師,這里有我自己整理了一套最新的python系統(tǒng)學(xué)習(xí)教程,包括從基礎(chǔ)的python腳本到web開發(fā)、爬蟲、數(shù)據(jù)分析、數(shù)據(jù)可視化、機(jī)器學(xué)習(xí)等。想要這些資料的可以關(guān)注小編,并在后臺(tái)私信小編:“01”即可領(lǐng)取。

          華碩冠名,中關(guān)村在線攜手華碩、七彩虹等知名硬件廠商在年底推出的重磅活動(dòng)——2015年度游戲攢機(jī)大賽已經(jīng)完美落幕。其中冠軍配置已經(jīng)揭曉,獲獎(jiǎng)網(wǎng)友為:默默的走路。目前冠軍配置硬件已由華碩提供至ZOL,下面我們就來為大家進(jìn)行裝機(jī)配置直播。

          10:09 2016-01-22

          玩家們稍等片刻,我們的編輯同學(xué)正在把硬件拆包以及搭建拍攝臺(tái),10:30我們將正式開啟裝機(jī)直播~

          10:13 2016-01-22

          在等待的過程中我們?cè)诨仡櫼幌?015年華碩杯攢機(jī)大賽的盛況吧!http://diy.zol.com.cn/topic/5544554.html#t1

          10:25 2016-01-22

          我想現(xiàn)在直播前最為激動(dòng)的網(wǎng)友一定是冠軍:默默的走路。將會(huì)在接下來的時(shí)間里親眼目睹自己的游戲裝備被搭建的全過程~

          10:31 2016-01-22

          好了,身在ZOL評(píng)測(cè)室的編輯已經(jīng)準(zhǔn)備就緒,下面我們就來一睹2015年華碩杯攢機(jī)大賽冠軍配置裝機(jī)全過程吧!

          10:36 2016-01-22

          下面我們來看一下這套主機(jī)的所有配件吧!CPU:Intel i3-4170 ,主板:華碩B85-G,內(nèi)存:威剛 游戲威龍8G DDR3 1600,硬盤:希捷1T 7200轉(zhuǎn) 64M,SSD:閃迪120G,顯卡:華碩猛禽GTX960-DC2OC-2GD5,機(jī)箱:先馬 碳立方,電源:航嘉 冷靜王至強(qiáng)版

          10:40 2016-01-22

          在開始裝機(jī)之前我們來插播一條溫馨提示哈~此次大賽除了冠軍獲得者以外,想必其他獲獎(jiǎng)網(wǎng)友都收到了相應(yīng)獎(jiǎng)品,如果沒收到的玩家請(qǐng)聯(lián)系:ZOL邱邱,他的郵箱是:qiu.shiqian@zol.com.cn

          10:44 2016-01-22

          對(duì)于主流游戲玩家一定非常關(guān)注顯卡的性能,這款華碩STRIX-GTX 960-DC2OC-2GD5,在核心方面這款顯卡采用了最新的第二代麥克斯韋架構(gòu)GM206圖形核心,具備更低的功耗,經(jīng)濟(jì)性更好。6pin電源接口的設(shè)置也為這款顯卡的超頻操作做出了準(zhǔn)備。更主要的是具有蠻高的性價(jià)比。

          10:48 2016-01-22

          這次直播我們將記錄主機(jī)組裝的全過程,對(duì)于小白玩家來說也是非常實(shí)用,如果不太會(huì)裝機(jī)的玩家不妨仔細(xì)觀看哦~

          10:52 2016-01-22

          首先,我們先將CPU安裝,玩家要注意的是,CPU的三角標(biāo)與主板上面的三角標(biāo)對(duì)準(zhǔn)統(tǒng)一方向,千萬不要四個(gè)方向亂試!因?yàn)獒樐_很脆弱,一不小心弄完可就麻煩了!

          10:54 2016-01-22

          然后把拉桿扣下,CPU我們就安裝完成啦!

          11:00 2016-01-22

          然后將CPU風(fēng)扇安好,因?yàn)槭窃b散熱器,所以在散熱器底部自帶硅脂。如果是選配的散熱器玩家一定記得要在安裝之前均勻的涂抹硅脂!

          11:04 2016-01-22

          我看到名為:全真道士行天下的網(wǎng)友,回復(fù)說:這配置不便宜吧!其實(shí)恰恰相反,這套配置主打的就是網(wǎng)吧游戲型主機(jī)高性價(jià)比的特點(diǎn)~

          11:09 2016-01-22

          哦對(duì)!在這里提醒玩家一點(diǎn)的就是!此次的CPU散熱器采用的是下壓式,所以沒有朝向的問題。如果玩家購(gòu)買的是塔式散熱器,在風(fēng)扇朝向方面是有講究的~各位網(wǎng)友稍等一下哈,我找一下素材,讓小白玩家了解一下~

          11:15 2016-01-22

          塔式散熱器的方向能夠影響機(jī)箱內(nèi)部的整體風(fēng)道,所以以單風(fēng)扇為例這種將CPU風(fēng)扇面向內(nèi)存插槽一側(cè),將廢熱排出機(jī)箱背部出風(fēng)口是最佳的散熱效果。

          11:18 2016-01-22

          好了 接下來我們就來安裝電源了,在這里玩家要注意的是,現(xiàn)在主流機(jī)箱基本采用的都是下置電源位設(shè)計(jì),電源風(fēng)扇應(yīng)該向下安裝,因?yàn)闄C(jī)箱電源風(fēng)扇是用來吸風(fēng)的,如果將電源風(fēng)扇朝上的話,它就會(huì)吸取上方顯卡產(chǎn)生的熱風(fēng),不利于電源散熱。記住哦!電源風(fēng)扇向下安裝!重要的事情說三遍!電源風(fēng)扇向下安裝!電源風(fēng)扇向下安裝!電源風(fēng)扇向下安裝!

          11:22 2016-01-22

          電源安裝之后呢,我們就該來安裝主板以及跳線了。剛才在評(píng)測(cè)室裝機(jī)的同事我跟我說安裝過程會(huì)稍微慢一下,因?yàn)闉榱四軌蚪o冠軍獲得者一個(gè)美觀的機(jī)箱,他把線要理的更加細(xì)致,所以玩家們不要著急哦,稍后我們看看他把線打理的如何吧!

          11:26 2016-01-22

          其實(shí)安裝跳線并不復(fù)雜,玩家只需要把對(duì)應(yīng)的英文標(biāo)示接好就可以了,下面我們就來帶大家看一看這些英文標(biāo)示都代表什么意思吧!

          POWER SW:機(jī)箱面板開機(jī)按鈕

          RESET SW:重啟按鈕

          POWER LED(+/-):電源指示燈

          H.D.D LED:硬盤指示燈線 USB:連接機(jī)箱USB接口

          HD AUDIO:機(jī)箱前置音頻

          11:31 2016-01-22

          這樣的CPU供電理線的方式還挺好看!擁有同款機(jī)箱的玩家你們也是這么做的嗎?

          11:35 2016-01-22

          接下來就是安裝顯卡了,這塊沒什么好說的~就是別忘記插供電線~

          11:36 2016-01-22

          硬盤安裝~現(xiàn)在基本上市售的機(jī)箱都是免工具安裝設(shè)計(jì),很方便的~

          11:40 2016-01-22

          看我們裝機(jī)的同事多貼心~連SATA線都理的很規(guī)整~

          11:41 2016-01-22

          大家是不是想看看這位裝機(jī)的暖男長(zhǎng)什么樣呢?待會(huì)我給大家公布哈~

          11:44 2016-01-22

          在評(píng)論中我看到了,Longstrovsky這位網(wǎng)友說:“說好的免工具呢 螺絲不還是自己上”?其實(shí)這個(gè)不是手?jǐn)Q螺絲,只是4個(gè)固定釘~只需要把硬盤架打開,然后對(duì)準(zhǔn)孔位插上即可固定~

          11:49 2016-01-22

          好了~機(jī)器組裝完成啦!這就是2015年華碩杯攢機(jī)大賽冠軍配置主機(jī),我們將在下周一把這款主機(jī)發(fā)送給網(wǎng)友:默默的走路。在發(fā)送之前,我們也會(huì)對(duì)這套主機(jī)的性能進(jìn)行一下測(cè)試,并且于近日在diy.zol.com.cn進(jìn)行公布,感興趣的玩家不妨多多關(guān)注!

          11:52 2016-01-22

          哦對(duì)!裝機(jī)暖男的靚照還沒公布~那我們就以他的靚照作為2015年華碩杯攢機(jī)大賽冠軍配置裝機(jī)直播的結(jié)尾吧!感謝大家的觀看!更多精彩內(nèi)容或者有獎(jiǎng)活動(dòng)請(qǐng)隨時(shí)關(guān)注中關(guān)村在線DIY頻道:diy.zol.com.cn~


          主站蜘蛛池模板: 无码人妻一区二区三区免费视频| 国产福利电影一区二区三区,亚洲国模精品一区 | 久久婷婷色一区二区三区| 女人18毛片a级毛片一区二区| 国产在线视频一区二区三区98 | 国产成人一区二区在线不卡| 亚洲第一区精品观看| 中文字幕一区二区三区5566| 日韩国产精品无码一区二区三区| 久久久无码精品人妻一区| 亚洲成AV人片一区二区密柚| 国产高清视频一区三区| 暖暖免费高清日本一区二区三区 | 亚洲国产成人久久综合一区77| 免费高清在线影片一区| 精品无码国产一区二区三区麻豆| 中文字幕AV无码一区二区三区| 国产精品久久一区二区三区| 亚洲香蕉久久一区二区| 亚洲一区二区三区久久久久| 国产一区二区三区电影| 国产大秀视频一区二区三区| 韩国精品福利一区二区三区| 在线观看视频一区二区| 日本一区高清视频| 精品成人一区二区三区免费视频| 色屁屁一区二区三区视频国产| 相泽南亚洲一区二区在线播放| 四虎在线观看一区二区| 国产视频一区二区| 成人久久精品一区二区三区| 中文字幕一区一区三区| 久久99精品波多结衣一区| 久久免费精品一区二区| 国产精品 视频一区 二区三区| 精品乱码一区内射人妻无码| 国产一区二区三区小向美奈子 | 国产嫖妓一区二区三区无码| 亚洲国产欧美国产综合一区| 中文字幕AV一区二区三区人妻少妇| 亚洲福利一区二区精品秒拍|