看板 C_Sharp 關於我們 聯絡資訊
  這是用萬惡的反組譯程式看來的...,因為MS的設計師都是高手,所以我也想偷學 幾手。先前想找出能夠WPF、WinForm通用的跨執行緒存取UI方式,但是不知道是我的關 鍵字很不關鍵,還是Google大神真的神不起來,而且MSDN論壇也沒人回應,所以只好自 己想辦法。   Windows Form的範例通常是呼叫繼承於System.Windows.Form.Control的Invoke或 BeginInvoke方法,而WPF則是要呼叫System.Windows.Conrtol的Dispatcher屬性中的 Invoke或BeginInvoke方法。      確實,這兩個方法可以達成需求,但是之前我把程式寫成Dll要給WinForm跟WPF參 考來做介面的時候就出現很大的窘境。我希望能夠讓用於視覺化介面顯示資料進度的事 件可以在Dll內部就寫好跨執行緒,而不用到撰寫UI的時候在各平台實作。   這是看了BackgroundWorker的ReportProgress方法怎麼做到跨執行緒,然後才知道 有這麼強大的類別。   [SynchronizationContext 類別]   如果看不懂Post方法傳送委派內容的匿名方法 (Anonymous Method) ,請參考 Lambda 運算式。如果你還是看不懂,那簡單來說它就是建立一個匿名方法並存入這個委 派的執行個體,引數內容(小括號內)是根據委派的規則,而大括號是方法主體。例如 SynchronizationContext.Post方法必須傳送一個SendOrPostCallBack委派執行個體。 這個委派是一個不回傳(Void)且有一個Object型別變數作為引數的方法。所以小括號內 就建立一個變數 "obj" 接收方法引數,不用宣告變數的型別,因為委派已經幫你決定了。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace Test { public class Progame { // Main程式進入點,這裡不重要,只是方便你複製貼上就可編譯測試而已。 public static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new myForm()); } } public partial class myForm : Form { // 先宣告一個全域變數以便儲存主要執行緒的同步處理物件執行個體。 SynchronizationContext mainThread; // 這是用來儲存稍後用於測試的次要執行緒。 Thread myThread; public myForm() { //這是IDE自動建立的UI初始化方法,不重要。 InitializeComponent(); //呼叫SynchronizationContext的靜態屬性Current,且把get值存到       //mainThread變數內。 mainThread = SynchronizationContext.Current; } private void myMethod() { //底下這行如果呼叫myThread.Start()絕對會出現例外狀況。 //this.Text = " Finished!!"; //mainThread的值已經在Form類別的建構函式存入,因此現在可以使用。 //這是重頭戲,SynchronizationContext有兩種跨執行緒存取方法可供使       //用。Post(非同步,類似Control.BeginInvoke(delegate))、Send(同步       //,類似Control.Invoke(delegate)) mainThread.Post ( new SendOrPostCallback ( //匿名方法的引數 (obj) //語彙基元又稱為 Lambda 運算子。 => //匿名方法主體 { this.Text = (String)obj; } ) , "Finished!!" ); } private void StartBT_Click(object sender, EventArgs e) { if (myThread != null && !myThread.IsAlive && myThread.ThreadState != ThreadState.Stopped) myThread.Start(); else { myThread = new Thread(new ThreadStart(myMethod)); StartBT_Click(null, null); } } //此行以下完全不重要。 private System.ComponentModel.IContainer components = null; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { this.StartBT = new System.Windows.Forms.Button(); this.SuspendLayout(); // // StartBT // this.StartBT.Location = new System.Drawing.Point(103, 58); this.StartBT.Name = "StartBT"; this.StartBT.Size = new System.Drawing.Size(75, 23); this.StartBT.TabIndex = 0; this.StartBT.Text = "Start"; this.StartBT.UseVisualStyleBackColor = true; this.StartBT.Click += new System.EventHandler(this.StartBT_Click); // // myForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(292, 142); this.Controls.Add(this.StartBT); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Name = "myForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "myForm"; this.ResumeLayout(false); } private System.Windows.Forms.Button StartBT; } } -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 58.86.18.20 ※ 編輯: optimist9266 來自: 218.160.112.198 (05/15 22:51)
F23ko:好深奧.... 05/16 16:00
※ 編輯: optimist9266 來自: 58.86.18.17 (06/05 02:29)