【发布时间】:2009-08-16 22:05:30
【问题描述】:
我正在开发一个免费、简单、多平台的热键启动器工具,用 Ruby 编写。
现在我正在努力解决 Windows 实现的一些线程问题。 下面显示的粗略概念证明代码在我的日常使用中已经可靠地工作:
HotkeyProcessor#process_keypress(脚注 1)在按键被按下时被 C 代码调用并随后处理按键事件。
问题
但是,当 process_keypress 启动一个线程 执行一些耗时的工作(脚注 2)时,会出现一个细微的缺陷: 该程序将大部分时间花在 C 扩展中,等待 get_message(脚注 3)返回——这在设计上永远不会发生。同时不会运行 Ruby 线程。 线程执行仅在 Ruby 级代码处于控制状态时发生,因此仅在 #process_keypress 处于活动状态时每个按键事件后的几毫秒内发生。
在这种情况下是否可以连续并发执行? 感谢您的任何建议!
require 'hotkey_processor'
def slowly_do_stuff
5.times { |i| sleep(0.1); print "#{i} " }
end
module HotkeyProcessor
def self.process_keypress(code, down) # footnote 1
print '. '
slowly_do_stuff if code == 65 and down # A pressed
Thread.new {slowly_do_stuff} if code == 66 and down # B pressed # footnote 2
true
end
end
puts 'Press A, B and other keys.'
HotkeyProcessor.start
热键处理器:
#include "ruby.h"
#include "windows.h"
#include <stdio.h>
int process_keypress_function;
VALUE HotkeyProcessor;
HHOOK keyboard_hook;
LRESULT CALLBACK callback_function(int Code, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT kbd = (PKBDLLHOOKSTRUCT)lParam;
if (Code < 0 || Qtrue == rb_funcall(HotkeyProcessor,
process_keypress_function,
2,
INT2NUM(kbd->vkCode), /* code */
(wParam == WM_KEYDOWN ||
wParam == WM_SYSKEYDOWN) ?
Qtrue : Qfalse)) /* down */
{
return CallNextHookEx(keyboard_hook, Code, wParam, lParam);
}
else
return 1;
}
static BOOL get_message(MSG *msg)
{
return GetMessage(msg, 0, 0, 0);
}
static VALUE start(VALUE self)
{
HMODULE Module = GetModuleHandle(NULL);
MSG msg;
keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL,
(HOOKPROC) callback_function,
Module,
0);
get_message(&msg); /* footnote 3 */
/* Never get here. Wait forever for get_message() to return
to keep the program alive and responding to callbacks. */
return self;
}
static VALUE process_keypress(VALUE self, VALUE code)
{
return Qnil;
}
void Init_hotkey_processor() {
HotkeyProcessor = rb_define_module("HotkeyProcessor");
rb_define_module_function(HotkeyProcessor,
"process_keypress",
process_keypress,
1);
rb_define_module_function(HotkeyProcessor,
"start",
start,
0);
process_keypress_function = rb_intern("process_keypress");
}
【问题讨论】:
标签: c ruby multithreading winapi callback