我最近在InfoQ上看到了关于Erlang的视频,在该视频中,其中一位创作者介绍了如何替换消息循环的行为.
他只是发送一条消息,其中包含新版本的消息循环代码的lambda,然后调用该消息而不是再次调用旧循环.
这段代码是在Erlang中热插拔的吗?或者是其他更原生的功能?
在尝试将我的游戏引擎移植到mac时,我偶然发现了一个基本(但很大)的问题.在Windows上,我的主要代码看起来像这样(非常简化):
PeekMessage(...) // check for windows messages
switch (msg.message)
{
case WM_QUIT: ...;
case WM_LBUTTONDOWN: ...;
...
}
TranslateMessage(&msg);
DispatchMessage (&msg);
for (std::vector<CMyBackgroundThread*>::iterator it = mythreads.begin(); it != mythreads.end(); ++it)
{
(*it)->processEvents();
}
... do other useful stuff like look if the window has resized and other stuff...
drawFrame(); // draw a frame using opengl
SwapBuffers(hDC); // swap backbuffer/frontbuffer
if (g_sleep > 0) Sleep(g_sleep);
Run Code Online (Sandbox Code Playgroud)
我已经读过这不是mac方式.mac方式是检查某种事件,例如屏幕的v-sync以呈现新帧.但正如你所看到的,我想做的不仅仅是渲染,我希望其他线程能够工作.有些线程需要比每1/60秒更快地调用一次.(顺便说一句,我的线程基础结构是:线程将事件放入同步队列中,主线程调用processEvents来处理主线程内该同步队列中的项目.这用于网络内容,图像加载/处理内容,perlin噪声一代等...等...)
我希望能够以类似的方式做到这一点,但很少有关于此的信息.我不介意将渲染放在v-sync事件上(我也将在Windows上实现),但我希望对其余代码有更多响应.
以这种方式看待它:我很乐意能够处理其余部分,而GPU正在做任何事情,我不想等待v-sync然后开始做已经处理过的东西才开始将内容发送到GPU.你明白我的意思吗?
如果我需要从完全不同的角度来看待这个问题,请告诉我.
如果我需要阅读书籍/指南/教程/任何内容,请告诉我要阅读的内容!
我不是可可开发人员,我不是对象程序员,我的游戏引擎完全是用C++编写的,但我知道我的方式足以让xcode出现并显示我在该窗口内绘制的内容.它只是不像我的Windows版本更新,因为我不知道如何正确.
更新:我甚至认为我需要某种循环,即使我想在垂直回扫上同步.MacOSX文档中的OpenGL编程显示,这是通过设置SwapInterval来完成的.因此,如果我理解正确,在Mac上实时渲染时,我总是需要某种循环,使用swapInterval设置来降低功耗.这是真的?
后台线程可以配置为接收窗口消息.您可以使用发布消息到线程PostThreadMessage.退出该消息循环的正确方法是什么?
在将消息发布到后台线程之前,线程需要通过调用PeekMessage以下内容来确保创建消息队列:
procedure ThreadProcedure;
var
msg: TMsg;
begin
//Call PeekMessage to force the system to create the message queue.
PeekMessage(msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
end;
Run Code Online (Sandbox Code Playgroud)
现在外面的世界能够将消息发布到我们的线程:
PostThreadMessage(nThreadID, WM_ReadyATractorBeam, 0, 0);
Run Code Online (Sandbox Code Playgroud)
我们的线程处于GetMessage循环中:
procedure ThreadProcedure;
var
msg: TMsg;
begin
//Call PeekMessage to force the system to create the message queue.
PeekMessage(msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
//Start our message pumping loop.
//GetMessage will return false when it receives a WM_QUIT
// GetMessage can return -1 if …Run Code Online (Sandbox Code Playgroud) 最近我尝试在自己的线程中放置一个窗口的消息循环,我想知道为什么它从未收到任何消息,但我已经知道Windows将消息发布到创建窗口的线程.如何在一个线程中创建一个窗口并导致另一个线程接收该窗口的消息?我已经看过PostThreadMessage函数,但我相信它还需要创建窗口的线程来监听消息,这正是我试图避免的,所以这个函数不是我需要的.
这似乎是一个常见的问题,我花了很多时间谷歌搜索答案,但我找不到一个.
erlang中的消息循环如何工作,它们在处理消息时是否同步?
据我所知,循环将从"接收"消息开始,然后执行某些操作并点击循环的另一次迭代.
那必须同步吗?对?
如果多个客户端将消息发送到同一个消息循环,那么所有这些消息都会排队并一个接一个地执行,或者?
要在并行处理多个消息,您必须在不同的进程中生成多个消息循环,对吧?
还是我误解了所有这些?
曾几何时,我记得这些东西.随着时间的推移,我的理解已经淡化,我的意思是刷新它.
我记得,任何所谓的单线程应用程序都有两个线程:
a)具有指向main或DllMain入口点的指针的主线程; 和
b)对于具有一些UI的应用程序,运行WndProc的UI线程(也称为辅助线程),即执行WndProc的线程,该线程接收Windows发布给它的消息.简而言之,执行Windows消息循环的线程.
对于UI应用程序,主线程处于阻塞状态,等待来自Windows的消息.当它收到它们时,它会将它们排队并将它们分派到消息循环(WndProc)并启动UI线程.
根据我的理解,处于阻塞状态的主线程是这样的:
while(getmessage(/* args &msg, etc. */))
{
translatemessage(&msg, 0, 0);
dispatchmessage(&msg, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)
Application.Run( new System.Windows.Forms() );
Run Code Online (Sandbox Code Playgroud)
这就是他们所谓的调度员吗?
我的问题是:
a)我的上述理解是否正确?
b)调度员到底是什么名字?
c)指向一个资源,我可以从Windows/Win32的角度更好地理解线程,然后将它与C#等高级语言联系起来.佩佐尔德在他的史诗作品中不遗余力地讨论这个问题.
虽然我相信我有点对,但确认会有所缓解.
我必须编写一个C#API来注册全局热键.要接收WM_HOTKEY消息,我使用a System.Windows.Forms.NativeWindow并运行自己的消息循环System.Windows.Forms.Application.Run(ApplicationContext).当用户想要注册一个热键时,他必须运行一个叫RegisterHotkey()停止消息循环的方法System.Windows.Forms.ApplicationContext.ExitThread(),将热键注册到RegisterHotKey()(P/Invoke)函数并再次启动消息循环.这是必需的,因为RegisterHotKey()必须在创建窗口的同一个线程中调用,该窗口必须在运行消息循环的同一个线程中实例化.
问题是,如果用户RegisterHotkey()在启动正在运行消息循环的线程后不久调用该方法,则会在ApplicationContext.ExitThread()之前调用Application.Run(ApplicationContext),因此应用程序将无限期地阻塞.有人知道等待消息循环启动的方法吗?
提前致谢!
我只是尝试在每次按钮点击时都运行一个新线程,这应该创建一个新表单.我在MainForm中的按钮单击事件中尝试了这个:
private void button1_Click(object sender, EventArgs e)
{
worker1 = new Thread(new ThreadStart(thread1));
worker2 = new Thread(new ThreadStart(thread2));
worker1.Start();
worker2.Start();
}
private void thread1()
{
SubForm s = new SubForm();
s.Show();
}
private void thread2()
{
SubForm s = new SubForm();
s.Show();
}
Run Code Online (Sandbox Code Playgroud)
子窗体按钮单击事件中的代码如下所示:
private void button1_Click(object sender, EventArgs e)
{
int max;
try
{
max = Convert.ToInt32(textBox1.Text);
}
catch
{
MessageBox.Show("Enter numbers", "ERROR");
return;
}
progressBar1.Maximum = max;
for ( long i = 0; i < max; i++)
{ …Run Code Online (Sandbox Code Playgroud) 是否可以在没有窗口的情况下使用Windows Raw Input API(即从控制台应用程序)?
我尝试过使用RegisterRawInputDevices,但我的消息循环似乎没有从GetMessage 获取任何事件,因此只是"挂起".
我正在为SetWindowsHookExAPI 编写一个实用程序单元.
要使用它,我想要一个这样的界面:
var
Thread: TKeyboardHookThread;
begin
Thread := TKeyboardHookThread.Create(SomeForm.Handle, SomeMessageNumber);
try
Thread.Resume;
SomeForm.ShowModal;
finally
Thread.Free; // <-- Application hangs here
end;
end;
Run Code Online (Sandbox Code Playgroud)
在我当前的实现中,TKeyboardHookThread我无法正确退出线程.
代码是:
TKeyboardHookThread = class(TThread)
private
class var
FCreated : Boolean;
FKeyReceiverWindowHandle : HWND;
FMessage : Cardinal;
FHiddenWindow : TForm;
public
constructor Create(AKeyReceiverWindowHandle: HWND; AMessage: Cardinal);
destructor Destroy; override;
procedure Execute; override;
end;
function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
S: KBDLLHOOKSTRUCT;
begin
if nCode < 0 then begin
Result …Run Code Online (Sandbox Code Playgroud) message-loop ×10
.net ×2
c# ×2
delphi ×2
erlang ×2
winapi ×2
windows ×2
winforms ×2
c++ ×1
cocoa ×1
console ×1
delphi-2007 ×1
dispatcher ×1
hotswap ×1
raw-input ×1