Delphi中纤程的使用
<p>首先我们来看看纤程的定义</p><p><strong> 纤程(来自百科):</strong></p>
<p><strong> </strong>纤程是Windows为了将Unix服务程序更好的移植到Windows上而创建的,</p>
<div class="para"> 线程是在Windows内核中实现的,纤程是在用户模式下实现的,内核对纤程一无所知,内核会根据我们定义的算法来对纤程进行调度。</div>
<div class="para"> 一个线程可以包含一个或多个纤程。多个纤程可以使用单个线程来运行。单个纤程也可以被多个线程运行,但每次只能有一个线程运行它。</div>
<div class="para"> 纤程一定要通过线程来关联它。</div>
<div class="para"> </div>
<div class="para"> </div>
<div class="para">Delphi中关于纤程的函数或者WindowsAPI有: </div>
<div class="para">
<p>function CreateFiber(<span style="background-color: rgba(255, 153, 0, 1)">dwStackSize</span>: DWORD; <span style="background-color: rgba(153, 204, 0, 1)">lpStartAddress</span>: TFNFiberStartRoutine; <span style="background-color: rgba(255, 255, 0, 1)">lpParameter</span>: Pointer): Pointer;</p>
<p style="margin-left: 60px">分配纤程对象,为其分配一个堆栈,并设置执行函数。如果函数成功,则返回值是纤程的地址。如果函数失败,则返回值为nil。</p>
<p style="margin-left: 60px">当你使用CreateFiber(Ex)函数创建一个纤程之后,该纤程不会执行,因为系统不会自动调度它。你必须调用函数SwitchToFiber来告诉系统你想要哪个纤程执行。</p>
<p style="margin-left: 60px"><span style="background-color: rgba(255, 153, 0, 1)">dwStackSize</span>:堆栈的初始大小,以字节为单位。 如果此参数为零,则新纤程使用可执行文件的默认堆栈大小。</p>
<p style="margin-left: 60px"><span style="background-color: rgba(153, 204, 0, 1)">lpStartAddress<span style="background-color: rgba(255, 255, 255, 1)">:指向由纤程执行的应用程序定义函数的指针(纤程要执行的功能函数)。 在另一纤程使用此地址调用SwitchToFiber功能之前,不会开始执行新创建的纤程。</span></span></p>
<p style="margin-left: 60px"><span style="background-color: rgba(255, 255, 0, 1)">lpParameter<span style="background-color: rgba(255, 255, 255, 1)">:传递给纤程的变量的指针。 纤程可以使用GetFiberData宏检索此数据。</span></span></p>
<p style="margin-left: 60px"><span style="background-color: rgba(255, 255, 0, 1)"><span style="background-color: rgba(255, 255, 255, 1)">该函数并不能直接运行纤程指定的函数,需要通过 函数 </span></span>ConvertThreadToFiber 将当前的线程转化为纤程才可使用。</p>
<p style="margin-left: 60px"> </p>
<p style="margin-left: 60px"> </p>
<p>function ConvertThreadToFiber(<span style="background-color: rgba(255, 153, 0, 1)">lpParameter</span>: Pointer): DWORD; </p>
<p> 将当前线程转换为纤程。 在调度其他纤程之前,必须将线程转换为纤程。</p>
<p style="margin-left: 30px">如果函数成功,则返回值是纤程的地址。如果函数失败,则返回值为nil。</p>
<p style="margin-left: 30px"><span style="background-color: rgba(255, 153, 0, 1)">lpParameter<span style="background-color: rgba(255, 255, 255, 1)">:传递给纤程的变量的指针。 纤程可以使用GetFiberData宏检索此数据。</span></span></p>
<p style="margin-left: 30px"> </p>
<p> 只有纤程才能执行其他纤程。 如果线程需要执行纤程,则必须调用ConvertThreadToFiber或ConvertThreadToFiberEx来创建一个区域来保存纤程状态信息。 线程现在是当前的纤程。 该纤程的状态信息包括<span style="background-color: rgba(255, 153, 0, 1)">lpParameter</span>指定的纤程数据。</p>
<p> </p>
<p>BOOL WINAPI ConvertFiberToThread(void);</p>
<p>该函数释放ConvertThreadToFiber函数分配的资源。 调用此函数后,您无法从线程调用任何纤程功能。</p>
<p>要编译使用此功能的应用程序,需要Windows Vista 或者 Windows XP;(--------除此之外的系统不能用了 :( ------------ )</p>
<p>不过我试过貌似可以手动加载这个函数,通过LoadLibrary。</p>
<p> </p>
<p>先看个例子:</p>
<p> 我们先创建个线程对象,然后在线程中创建纤程,在将线程转为纤程</p>
<p><strong><span style="background-color: rgba(255, 255, 153, 1)">线程代码:</span></strong></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">unit</span><span style="color: rgba(0, 0, 0, 1)"> ThrdFiber;
</span><span style="color: rgba(0, 0, 255, 1)">interface</span>
<span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)">
Classes,Windows,SysUtils,Dialogs;
</span><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TFiber </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TThread)
</span><span style="color: rgba(0, 0, 255, 1)">private</span>
<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> Private declarations </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">protected</span>
<span style="color: rgba(0, 0, 255, 1)">procedure</span> Execute; <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
<span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(Suspended:Boolean);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>
<span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)"> Main;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> TFiber </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
hwnd:Pointer;
x:Integer;
hThread:Cardinal;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span> SetText(P:Pointer);<span style="color: rgba(0, 0, 255, 1)">stdcall</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
i:Integer;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> i := PInteger(P)^ <span style="color: rgba(0, 0, 255, 1)">downto</span> <span style="color: rgba(128, 0, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">do</span>
<span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
MainFrm.Caption:</span>=<span style="color: rgba(0, 0, 0, 1)">IntToStr(i);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
SwitchToFiber(Pointer(hThread)); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里切换回1,然后后面释放 2</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">constructor</span> TFiber.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(Suspended: Boolean);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
FreeOnTerminate:</span>=<span style="color: rgba(0, 0, 0, 1)">True;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TFiber.Execute;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
x:</span>=<span style="color: rgba(128, 0, 128, 1)">5000</span><span style="color: rgba(0, 0, 0, 1)">;
hThread:</span>=ConvertThreadToFiber(<span style="color: rgba(0, 0, 255, 1)">nil</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 纤程 1</span>
hwnd:=CreateFiber(<span style="color: rgba(128, 0, 128, 1)">0</span>,@SetText,PInteger(@x));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 纤程 2</span>
SwitchToFiber(hwnd); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1 切换 2,那么2的释放就得切换回1来释放,如果没有切换回1,则下面的语句不会执行</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> ShowMessage('没有执行...');</span>
<span style="color: rgba(0, 0, 0, 1)"> DeleteFiber(hwnd);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">后面还可以使用ConvertFiberToThread来结束当前的线程</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>.</pre>
</div>
<p>暂时只了解这么多....</p>
<p> </p>
<p> </p>
<p> </p>
<p style="margin-left: 30px"> </p>
</div><br><br>
来源:https://www.cnblogs.com/Master-Qi/p/10918402.html
頁:
[1]