sun.yh
发表于 2021-1-19 11:38:45
怕你们误解,特地在9-12楼说了一下.net消息帧
.net开环OK,当然OK,开始就说了开环是OK的
sun.yh
发表于 2021-1-19 11:53:57
注意,也不要把.net消息帧插到宿主里面。因为原码是场景模拟。真实的消息环是封装的,没有源码的
sun.yh
发表于 2021-1-19 11:55:47
响应必须是win32可翻译的消息。我们看不到AR源码,所以不知道AR是否使用了.net特有消息
KearneyKang
发表于 2021-1-19 12:09:35
本帖最后由 KearneyKang 于 2021-1-19 12:22 编辑
目前给的办法是这样,跟研发沟通后,他们给的就是当前的这个解决办法。但是我已经就你说的C++消息环的问题也在同时跟他们进行沟通,看看有么有其他的方式解决
sun.yh
发表于 2021-1-20 21:02:39
问题发出的时候就说了.net消息环的是没有问题的。你这发回来告诉我加上.net消息环就OK了
还告诉我这个问题就这么处理,这样做不好吧
Lenka.Guo
发表于 2021-1-21 13:39:26
本帖最后由 Lenka.Guo 于 2021-1-21 13:44 编辑
您好,
因为你的使用方法比较特殊,C++引用Winform 项目。但Winform 机制项目的消息循环只能有一个,也因为您的用法比较特殊,我们和研发同事进行了沟通,主要是集中在C++ 调用Winform项目的消息循环如何处理的问题。我们也跟多名资深的.net 开发工程师沟通,在C++中重写Windows 消息循环是非常复杂的,很难做到。
参考资料
https://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/Dispatcher.cs,2471
sun.yh
发表于 2021-1-21 15:15:25
我跟踪到,改用这个Dispatcher.PushFrame(new DispatcherFrame())也是解决不了问题的。
sun.yh
发表于 2021-1-21 15:16:29
需要使用:UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
sun.yh
发表于 2021-1-21 15:21:36
我通过一步一步向前推,找到了private void RunMessageLoopInner(int reason, ApplicationContext context),是可以的。
进一步前推到UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
这个方法的第一个参数一值搞不定
那么就请帮忙看一下,这个消息环哪些代码会与问题有关
sun.yh
发表于 2021-1-21 15:22:26
bool UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(
IntPtr dwComponentID,
int reason,
int pvLoopData // PVOID
) {
int dwLocalComponentID = unchecked((int)(long)dwComponentID);
// Hold onto old state to allow restore before we exit...
//
int currentLoopState = currentState;
bool continueLoop = true;
if (!OleComponents.ContainsKey(dwLocalComponentID)) {
return false;
}
UnsafeNativeMethods.IMsoComponent prevActive = this.activeComponent;
try {
// Execute the message loop until the active component tells us to stop.
//
NativeMethods.MSG msg = new NativeMethods.MSG();
NativeMethods.MSG[] rgmsg = new NativeMethods.MSG[] {msg};
bool unicodeWindow = false;
UnsafeNativeMethods.IMsoComponent requestingComponent;
ComponentHashtableEntry entry = (ComponentHashtableEntry)OleComponents;
if (entry == null) {
return false;
}
requestingComponent = entry.component;
this.activeComponent = requestingComponent;
Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, "ComponentManager : Pushing message loop " + reason.ToString(CultureInfo.InvariantCulture));
Debug.Indent();
while (continueLoop) {
// Determine the component to route the message to
//
UnsafeNativeMethods.IMsoComponent component;
if (trackingComponent != null) {
component = trackingComponent;
}
else if (activeComponent != null) {
component = activeComponent;
}
else {
component = requestingComponent;
}
bool peeked = UnsafeNativeMethods.PeekMessage(ref msg, NativeMethods.NullHandleRef, 0, 0, NativeMethods.PM_NOREMOVE);
if (peeked) {
rgmsg = msg;
continueLoop = component.FContinueMessageLoop(reason, pvLoopData, rgmsg);
// If the component wants us to process the message, do it.
// The component manager hosts windows from many places.We must be sensitive
// to ansi / Unicode windows here.
//
if (continueLoop) {
if (msg.hwnd != IntPtr.Zero && SafeNativeMethods.IsWindowUnicode(new HandleRef(null, msg.hwnd))) {
unicodeWindow = true;
UnsafeNativeMethods.GetMessageW(ref msg, NativeMethods.NullHandleRef, 0, 0);
}
else {
unicodeWindow = false;
UnsafeNativeMethods.GetMessageA(ref msg, NativeMethods.NullHandleRef, 0, 0);
}
if (msg.message == NativeMethods.WM_QUIT) {
Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, "ComponentManager : Normal message loop termination");
Application.ThreadContext.FromCurrent().DisposeThreadWindows();
if (reason != NativeMethods.MSOCM.msoloopMain) {
UnsafeNativeMethods.PostQuitMessage((int)msg.wParam);
}
continueLoop = false;
break;
}
// Now translate and dispatch the message.
//
// Reading through the rather sparse documentation,
// it seems we should only call FPreTranslateMessage
// on the active component.But frankly, I'm afraid of what that might break.
// See ASURT 29415 for more background.
if (!component.FPreTranslateMessage(ref msg)) {
UnsafeNativeMethods.TranslateMessage(ref msg);
if (unicodeWindow) {
UnsafeNativeMethods.DispatchMessageW(ref msg);
}
else {
UnsafeNativeMethods.DispatchMessageA(ref msg);
}
}
}
}
else {
// If this is a DoEvents loop, then get out.There's nothing left
// for us to do.
//
if (reason == NativeMethods.MSOCM.msoloopDoEvents ||
reason == NativeMethods.MSOCM.msoloopDoEventsModal) {
break;
}
// Nothing is on the message queue.Perform idle processing
// and then do a WaitMessage.
//
bool continueIdle = false;
if (OleComponents != null) {
IEnumerator enumerator = OleComponents.Values.GetEnumerator();
while (enumerator.MoveNext()) {
ComponentHashtableEntry idleEntry = (ComponentHashtableEntry)enumerator.Current;
continueIdle |= idleEntry.component.FDoIdle(-1);
}
}
// give the component one more chance to terminate the
// message loop.
//
continueLoop = component.FContinueMessageLoop(reason, pvLoopData, null);
if (continueLoop) {
if (continueIdle) {
// If someone has asked for idle time, give it to them.However,
// don't cycle immediately; wait up to 100ms.Why?Because we don't
// want someone to attach to idle, forget to detach, and then ----
// the CPU.For Windows Forms this generally isn't an issue because
// our component always returns false from its idle request
UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, NativeMethods.QS_ALLINPUT, NativeMethods.MWMO_INPUTAVAILABLE);
}
else {
// We should call GetMessage here, but we cannot because
// the component manager requires that we notify the
// active component before we pull the message off the
// queue.This is a bit of a problem, because WaitMessage
// waits for a NEW message to appear on the queue.If a
// message appeared between processing and now WaitMessage
// would wait for the next message.We minimize this here
// by calling PeekMessage.
//
if (!UnsafeNativeMethods.PeekMessage(ref msg, NativeMethods.NullHandleRef, 0, 0, NativeMethods.PM_NOREMOVE)) {
UnsafeNativeMethods.WaitMessage();
}
}
}
}
}
Debug.Unindent();
Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, "ComponentManager : message loop " + reason.ToString(CultureInfo.InvariantCulture) + " complete.");
}
finally {
currentState = currentLoopState;
this.activeComponent = prevActive;
}
return !continueLoop;
}