推 F23ko:好深奧.... 05/16 16:00
※ 編輯: optimist9266 來自: 58.86.18.17 (06/05 02:29)
這是用萬惡的反組譯程式看來的...,因為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)