管理和缓存 UI 个对象
Manage and cache UI objects
我正在为 windows 资源管理器编写命名空间扩展。在扩展的上下文中没有 UI 线程。因此,当我创建一个 UI 对象并将其缓存以重用它时,我得到了跨线程异常。我明白为什么我会收到跨线程异常,但我不确定如何解决它。
有没有一种方法可以创建自己的 UI 线程,然后使用该线程来管理 UI 对象?我认为这会解决问题。
我可以通过编写自己的消息循环和 运行 UI 来解决这个问题。在下面的示例中,action 是我用来调用 UI.
的函数
internal class MessageLoop
{
private bool _running;
private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
[DllImport("user32.dll")]
static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")]
static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
public MessageLoop()
{
Start();
}
public void Start()
{
_running = true;
Thread t = new Thread(RunMessageLoop) {Name = "UI Thread", IsBackground = true};
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void RunMessageLoop()
{
while (_running)
{
while (_actions.Count > 0)
{
Action action;
if (_actions.TryDequeue(out action))
action();
}
MSG msg;
var res = GetMessage(out msg, IntPtr.Zero, 0, 0);
if (res <= 0)
{
_running = false;
break;
}
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
}
public void Stop()
{
_running = false;
}
public void AddMessage(Action act)
{
_actions.Enqueue(act);
}
}
我正在为 windows 资源管理器编写命名空间扩展。在扩展的上下文中没有 UI 线程。因此,当我创建一个 UI 对象并将其缓存以重用它时,我得到了跨线程异常。我明白为什么我会收到跨线程异常,但我不确定如何解决它。
有没有一种方法可以创建自己的 UI 线程,然后使用该线程来管理 UI 对象?我认为这会解决问题。
我可以通过编写自己的消息循环和 运行 UI 来解决这个问题。在下面的示例中,action 是我用来调用 UI.
的函数internal class MessageLoop
{
private bool _running;
private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
[DllImport("user32.dll")]
static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")]
static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
public MessageLoop()
{
Start();
}
public void Start()
{
_running = true;
Thread t = new Thread(RunMessageLoop) {Name = "UI Thread", IsBackground = true};
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void RunMessageLoop()
{
while (_running)
{
while (_actions.Count > 0)
{
Action action;
if (_actions.TryDequeue(out action))
action();
}
MSG msg;
var res = GetMessage(out msg, IntPtr.Zero, 0, 0);
if (res <= 0)
{
_running = false;
break;
}
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
}
public void Stop()
{
_running = false;
}
public void AddMessage(Action act)
{
_actions.Enqueue(act);
}
}