KevinRagsdale
TheNet Results
Voice:931-409-9899
Email: kevin@kevinragsdale.nethttp://kevinragsdale.net
Twitter:@KevinRagsdale
翻译:xinjie
Power by www.deelp.com
这一切都源于《微软Visual FoxPro顾问指南》2006年9月号上的一个简单问题。
问题:如果我可以在后台线程中运行,许多事情就更容易做了。有没有一种方法可以在VFP中创建多线程应用程序?
该问题由特约编辑Christof Wollenhaupt做出回答。
他的答复:这个问题有一个明确的答案。这取决于(你认为什么是多线程应用程序)。
从VFP6 ServicePack 3开始,我们就有能力在Visual FoxPro中创建多线程的DLLs。但这并不意味着我们在创建多线程应用程序,我们只是在创建多线程的DLLs。当你实例化一个位于DLL中的COM服务时,Visual FoxPro只能将其加载到与主程序相同的线程中。
实质上,如果你的DLL正在执行 "一个漫长的处理过程",Visual FoxPro(你的应用程序)必须等待 "一个漫长的处理过程 "完成才能继续。这可能会使用户感到困惑,因为你的应用程序对用户的操作没有反应,同时也为Windows在你的应用程序的标题栏上附加一个不那么漂亮的"(停止响应)"(图1)。
图1: Windows 提供的"有用的" 停止响应消息
本文介绍了Christof编写的一个C++ DLL "辅助工具",他在上面提到的解答部分做了进一步的详细解释。
01
—
到底什么是多线程?
依据我在书本、文章和无数谷歌搜索中看到的关于多线程的所有定义,多线程就是:在一个应用程序中同时执行多个活动的能力。如今,随着我们的多核CPU的出现,这一点更加真实。
来自维基百科:在单个处理器上,多线程通常通过分时复用(如多任务)发生:处理器在不同的线程之间切换。这种上下文切换通常发生得足够频繁,以至于用户认为这些线程或任务是在同一时间运行。在多处理器或多核系统上,线程或任务实际上是同时运行的,每个处理器或内核都在运行一个特定的线程或任务。
(On a single processor, multithreading generally occurs by time-division multiplexing (asin multitasking): the processor switches between different threads. Thiscontext switching generally happens frequently enough that the user perceivesthe threads or tasks as running at the same time. On a multiprocessor ormulti-core system, the threads or tasks will actually run at the same time,with each processor or core running a particular thread or task.)
来源:http://en.wikipedia.org/wiki/Multithreaded
02
—
多线程的优势有哪些?
对我来说,多线程的第一大优势很简单:应用程序用户界面的响应速度。
以前有人说过很多次,对于用户来说,你的应用程序的用户界面就是应用程序。根据我的经验,没有什么比一个没有反应的用户界面更让人觉得糟糕的用户界面(和糟糕的应用程序)了。
另一个优点是能够在不打断用户工作流程的情况下执行必要和/或可选的功能。我在几个应用程序中使用多线程请求,在后台检查程序的更新。如果发现有更新,应用程序会向用户通知其可用性。另一个应用程序在后台从几个不同的网站拉取各种信息,解析信息,写入表格等,当用户在应用程序中做其他事情时,根本没有意识到后台有多少工作在进行。简而言之,即使在忙于执行多项任务的情况下,该应用程序仍然对用户有反应。
03
—
“一个漫长的处理过程” 的简单示例
让我们来看看一个由多线程DLL中的SomeLengthyProcess触发的无响应UI。
我有一个名为SAMPLE.PJX的项目,它包含一个名为
SAMPLEMAIN.PRG,我把这个项目编译成一个多线程的DLL(SAMPLE.DLL在本次会议的源代码中)。
下面是SAMPLEMAIN.PRG的代码:
DEFINE CLASS EasyMTServer As Session OLEPUBLIC
PROCEDURE SomeLengthyProcess (toCallback)
** 我们需要声明 Sleep 这个 Windows API 函数 ** 确保进程可以持续 20 秒
DECLARE Sleep IN WIN32API Long
** 创建一个 FOR/ENDFOR 循环
LOCAL lnCount As Integer
** 在 VFP 主窗口输出一个字符串
FOR lnCount = 1 TO 20
** 在 VFP 主窗口输出 SYS(2015)的值
toCallback.DoCmd("? + ALLTRIM(SYS(2015))")
** 等待 1 秒
Sleep(1000)
ENDFOR
** 输出字符串 “Done!”
toCallback.DoCmd("? + 'Done!'")
CLEAR DLLS "Sleep"
ENDPROC
ENDDEFINE
看起来是一个漫长的过程,对吗?它应该需要20秒的时间来运行。在实例化COM服务(DLL)后,我将调用SomeLengthyProcess方法,并传入_VFP对象作为回调。在20秒内,DLL将创建一个SYS(2015)字符串(每秒一次),并告诉_VFP将该字符串写出到VFP主窗口。
从VFP命令窗口调用DLL看起来像这样:
loDLL = CREATEOBJECT("sample.EasyMTServer")
loDLL.SomeLengthyProcess(_VFP)
完美!我有了一个多线程的DLL,它在20秒内一直在忙碌,向VFP写回数据,以便我看到它在做什么。我有一个多线程的DLL,它保持20秒的忙碌,向我的VFP会话写回数据,这样我就可以看到它在做什么。但是,有一个问题。
我的VFP会话没有反应(图2)。我可以随意点击、双击甚至三击任何地方,但当SomeLengthyProcess运行时,什么也没有发生!我的VFP会话没有反应(图2)。
图 2:在单线程中并不能实现真正的多线程
在 VFP窗口周围点击会导致Windows在标题栏上附加之前显示的"停止响应 "信息。有时,VFP窗口(或您的应用程序)会褪色(图3),在Windows Vista/Windows 7中,您(或您的用户)可能会看到类似图4中的信息。
图3: 一个没有反应的应用程序,被Windows淡化了
图4: 当你的应用程序没有反应时,就不是很好玩儿的事了
正如我在简介中写的那样(根据Christof顾问回答中的信息),当你实例化一个位于DLL中的COM服务时,VFP只能将其加载到与主程序相同的线程中。因此,当SomeLengthyProcess在运行时,VFP IDE是不可用的。
04
—
一些 “辅助”工具
然而,正如Christof进一步解释的那样,并不是没有可能实现。即使你在VFP中创建了一个MTDLL,你也需要一个额外的辅助工具来创建一个新线程,初始化内存空间,并加载COM服务。
据我所知,有三个这样的"辅助 "工具(Christof在他的回答中都提到了这些工具):
• Remus Rusano 的 VFPMTAPP.DLL
• 来自 Calvin Hsia 博客的代码
• Christof 的 DMULT.DLL
请期待明天的更新,搞定多线程的正式代码就来啦。
写在最后面的话
加菲猫的VFP公众号接受投稿,一经采用,即有稿费,稿费暂定50元一篇。
加菲猫的vfp倡导用VFP极简混合开发,少写代码、快速出活,用VFP,但不局限于VFP,各种语言混合开发。
已经带领一百多名会员成功掌到VFP的黑科技,进入了移动互联网时代,接下来我们要进入物联网领域。