多线程编程(Context)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程编程(Context)相关的知识,希望对你有一定的参考价值。

转载请注明原文出处,http://www.cnblogs.com/flyingcloude/p/6992343.html

通过切换线程的Context内容,使用单线程模拟多线程运行。在程序中需要使用到的API主要有以下这些:

     GetThreadContext(HANDLE hThread, Context lpContext);

     说明:GetThreadContext,将hThread的上下文保存到lpContext中

     SetThreadContext(HANDLE hThread, const Context *lpContext);

     说明:SetThreadContext,将lpContext的内容保存到hThread的上下文中。

 

[cpp] view plain copy
 
  1. #include <windows.h>  
  2. #include <stdio.h>  
  3.   
  4. #define SEND_THREAD_ID  1  
  5. #define RECV_THREAD_ID  2  
  6.   
  7. const UINT uiTimerID = 10;  
  8.   
  9. HANDLE mainhandle;  
  10. CONTEXT send_context;  
  11. CONTEXT recv_context;  
  12.   
  13. HANDLE hd_send_thread;  
  14. HANDLE hd_recv_thread;  
  15.   
  16.   
  17. //如果hd_send_thread运行, thread_id = 1;  
  18. //如果hd_recv_thread运行, thread_id = 2;  
  19. int cur_thread_id = 0;  
  20.   
  21. void send_thread_func()  
  22. {  
  23.     static int send_msg_count = 0;  
  24.     while(1)  
  25.     {  
  26.         printf("send_msg_count:............................ %d\\n", send_msg_count++);  
  27.         Sleep(1000);  
  28.     }  
  29. }  
  30.   
  31. void recv_thread_func()  
  32. {  
  33.     static int recv_msg_count = 0;  
  34.     while(1)  
  35.     {  
  36.         printf("recv_msg_count: --------------------%d\\n", recv_msg_count++);  
  37.         Sleep(1000);  
  38.     }  
  39. }  
  40.   
  41.   
  42. VOID CALLBACK TimerFun(HWND hwnd, UINT a, UINT b, DWORD c)  
  43. {  
  44.     static int nCount = 0;  
  45.     printf("TimerFun nCount: %d\\n", nCount++);  
  46.     if(nCount == 0)  
  47.     {  
  48.         send_context.ContextFlags = CONTEXT_FULL;  
  49.         recv_context.ContextFlags = CONTEXT_FULL;  
  50.         GetThreadContext(mainhandle, &send_context); //保存主线程上下文  
  51.         GetThreadContext(mainhandle, &recv_context); //保存主线程上下文  
  52.         return;  
  53.     }  
  54.   
  55.     if(nCount % 2 == 1) //启动hd_send_thread  
  56.     {  
  57.         if(cur_thread_id != SEND_THREAD_ID)  
  58.         {  
  59.             SuspendThread(mainhandle);      //中止主线程的运行,模拟中断产生.但没有保存寄存器  
  60.             recv_context.ContextFlags = CONTEXT_FULL;  
  61.             GetThreadContext(mainhandle, &recv_context); //保存主线程上下文  
  62.             SetThreadContext(mainhandle, &send_context); //得到主线程上下文,为切换任务做准备  
  63.             cur_thread_id = SEND_THREAD_ID;  
  64.             ResumeThread(mainhandle);  
  65.         }  
  66.     }  
  67.     else  //启动hd_recv_thread  
  68.     {  
  69.         if(cur_thread_id != RECV_THREAD_ID)  
  70.         {  
  71.             SuspendThread(mainhandle);      //中止主线程的运行,模拟中断产生.但没有保存寄存器  
  72.             send_context.ContextFlags = CONTEXT_FULL;  
  73.             GetThreadContext(mainhandle, &send_context); //保存主线程上下文  
  74.             SetThreadContext(mainhandle, &recv_context); //得到主线程上下文,为切换任务做准备  
  75.             cur_thread_id = RECV_THREAD_ID;  
  76.             ResumeThread(mainhandle);  
  77.         }  
  78.     }  
  79. }  
  80.   
  81. int main()  
  82. {  
  83.     MSG msg;  
  84.   
  85.     SetTimer(NULL, uiTimerID, 1000, TimerFun);  
  86.   
  87.     hd_send_thread = CreateThread(NULL,  
  88.                                   0,  
  89.                                   (LPTHREAD_START_ROUTINE)send_thread_func,  
  90.                                   0,  
  91.                                   0,  
  92.                                   0);  
  93.     SuspendThread(hd_send_thread);  
  94.   
  95.     hd_recv_thread = CreateThread(NULL,  
  96.                                   0,  
  97.                                   (LPTHREAD_START_ROUTINE)recv_thread_func,  
  98.                                   0,  
  99.                                   0,  
  100.                                   0);  
  101.     SuspendThread(hd_recv_thread);  
  102.   
  103.     DuplicateHandle(GetCurrentProcess(),  
  104.                     hd_send_thread,   
  105.                     GetCurrentProcess(),   
  106.                     &mainhandle,   
  107.                     0,   
  108.                     TRUE,   
  109.                     2);  
  110.       
  111.     cur_thread_id = SEND_THREAD_ID;  
  112.     ResumeThread(hd_send_thread);  
  113.     ResumeThread(hd_recv_thread);  
  114.   
  115.   
  116.     while(GetMessage(&msg, NULL, 0, 0))  
  117.     {  
  118.         TranslateMessage(&msg);  
  119.         DispatchMessage(&msg);  
  120.     }   
  121.     return   0;  
  122. }  

 不知道为什么在main函数中,就将hd_send_thread、hd_recv_thread两个线程的上下文保存到send_context、recv_context中,然后再到定时器中断中进行切换就会出错,所以将这部分的代码也放在第一次进定时器中断的时候运行。

 

转载请注明原文出处,http://www.cnblogs.com/flyingcloude/p/6992343.html

以上是关于多线程编程(Context)的主要内容,如果未能解决你的问题,请参考以下文章

进程线程多进程多线程的优缺点

看完就知道在Github点赞近90KJava多线程笔记这么吃香,原因如下

Linux多线程编程

什么是Java多线程编程?

VB.net多线程编程问题

多线程实践—Python多线程编程