作者optimist9266 (Optimist)
看板C_Sharp
标题[心得] 跨执行绪存取控制项 (WPF、WinForm 通用)
时间Sat May 15 15:01:04 2010
这是用万恶的反组译程式看来的...,因为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)
1F:推 F23ko:好深奥.... 05/16 16:00
※ 编辑: optimist9266 来自: 58.86.18.17 (06/05 02:29)