同步 Invoke 事件





2.00/5 (2投票s)
从不同线程安全地调用控件的方法。
引言
Windows 窗体中的控件绑定到特定线程,并且不是线程安全的。因此,如果您从不同线程调用控件的方法,则必须使用控件的 Invoke 方法之一,将调用传递到正确的线程。
背景
Windows 窗体使用单线程公寓 (STA) 模型,因为 Windows 窗体基于固有的公寓线程化的本机 Win32 窗口。STA 模型意味着可以在任何线程上创建窗口,但创建后不能切换线程,并且所有对它的函数调用都必须在其创建线程上发生。在 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。
STA 模型要求,任何需要在控件的创建线程之外调用的控件上的方法都必须传递到(在控件的创建线程上执行)。基类 Control
提供了几种方法(Invoke
、BeginInvoke
和 EndInvoke
)来实现此目的。Invoke
进行同步方法调用,而 BeginInvoke
进行异步方法调用。
使用代码
使用属性 'InvokeRequired
' 来指示调用者是否必须在对控件进行方法调用时调用 Invoke 方法,因为调用者位于与控件创建线程不同的线程上。
public static class Utility
{
public static void SynchronizeInvokeEvent(object sender,
Delegate TargetEvent, EventArgs e)
{
if (TargetEvent != null)
{
Delegate[] InvocationList = TargetEvent.GetInvocationList();
foreach (Delegate TargetDelegate in InvocationList)
{
try
{
System.ComponentModel.ISynchronizeInvoke Target =
TargetDelegate.Target
as System.ComponentModel.ISynchronizeInvoke;
if (Target != null)
{
if (Target.InvokeRequired)
Target.Invoke(TargetDelegate, new object[] { sender, e });
else
TargetDelegate.DynamicInvoke(new object[] { sender, e });
}
else
{
TargetDelegate.DynamicInvoke(new object[] { sender, e });
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}
// You must add references to System.Management.dll
public class ProcessWatcher : IDisposable
{
public delegate void TaskManagerEventHandler(object sender,
TaskManagerEventArgs e);
public event TaskManagerEventHandler ProcessCreated;
private bool m_StartedWatcher;
private System.Management.ManagementEventWatcher m_CreateProcessWatcher;
public ProcessWatcher()
{
m_StartedWatcher = false;
}
public void Dispose()
{
StopWatcher();
GC.Collect();
GC.WaitForPendingFinalizers();
}
public void StartWatcher()
{
if (m_StartedWatcher)
return;
m_StartedWatcher = true;
System.Management.EventWatcherOptions eventOptions =
new System.Management.EventWatcherOptions();
eventOptions.BlockSize = 1;
eventOptions.Timeout = new TimeSpan(0, 0, 2);
m_CreateProcessWatcher = new System.Management.ManagementEventWatcher
(
"root\\CIMV2",
"SELECT * FROM __InstanceCreationEvent WITHIN 1 " +
"WHERE TargetInstance ISA \"Win32_Process\"",
eventOptions
);
m_CreateProcessWatcher.EventArrived +=
new System.Management.EventArrivedEventHandler(
OnCreateProcessWatcher_EventArrived);
m_CreateProcessWatcher.Start();
}
public void StopWatcher()
{
if (!m_StartedWatcher)
return;
m_StartedWatcher = false;
m_CreateProcessWatcher.Stop();
m_CreateProcessWatcher.EventArrived -=
new System.Management.EventArrivedEventHandler(
OnCreateProcessWatcher_EventArrived);
m_CreateProcessWatcher.Dispose();
m_CreateProcessWatcher = null;
}
void OnCreateProcessWatcher_EventArrived(object sender,
System.Management.EventArrivedEventArgs e)
{
int ProcessID;
if (int.TryParse(((System.Management.ManagementBaseObject)
e.NewEvent["TargetInstance"])["ProcessId"].ToString(),
out ProcessID))
{
OnCreateProcess(new TaskManagerEventArgs(
System.Diagnostics.Process.GetProcessById(ProcessID)));
}
}
private void OnCreateProcess(TaskManagerEventArgs e)
{
Utility.SynchronizeInvokeEvent(this, ProcessCreated, e);
}
public class TaskManagerEventArgs : EventArgs
{
private System.Diagnostics.Process m_Process;
public TaskManagerEventArgs(System.Diagnostics.Process Process)
{
m_Process = Process;
}
public System.Diagnostics.Process Process
{
get { return m_Process; }
}
}
}
public partial class Form1 : Form
{
private ProcessWatcher m_ProcessWatcher;
public Form1()
{
InitializeComponent();
m_ProcessWatcher = new ProcessWatcher();
m_ProcessWatcher.ProcessCreated += new
ProcessWatcher.TaskManagerEventHandler(
m_ProcessWatcher_ProcessCreated);
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
// Dispose ProcessWatcher here or in form disposing method;
m_ProcessWatcher.Dispose();
base.OnFormClosing(e);
}
private void m_ProcessWatcher_ProcessCreated(object sender,
ProcessWatcher.TaskManagerEventArgs e)
{
this.listBox1.Items.Add(e.Process.ProcessName);
}
private void m_StartProcessWatcherButton_Click(object sender, EventArgs e)
{
m_ProcessWatcher.StartWatcher();
}
private void m_StopProcessWatcherButton_Click(object sender, EventArgs e)
{
m_ProcessWatcher.StopWatcher();
}
}