我正在为 Windows 资源管理器编写命名空间扩展。在扩展的上下文中,没有 UI 线程。所以当我创建一个 UI 对象并缓存它以重用它时,我得到了跨线程异常。我理解为什么我会遇到跨线程异常,但我不知道如何解决它。
有没有办法可以创建自己的 UI 线程,然后使用该线程来管理 UI 对象?我认为这将解决问题。
我正在为 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);
}
}