queueuserworkitemqueueuserworkitem 线程池异步任务为什么没有被立即执行
queueuserworkitem 时间:2021-01-17 阅读:(
)
C# ThreadPool和Thread多线程 问
/ / 线程池示例
using System;
using System.Threading;
public class Test
{
// 存放要计算的数值的字段
static double number1 = -1;
static double number2 = -1;
public static void Main()
{
// 获取线程池的最大线程数和维护的最小空闲线程数
int maxThreadNum, portThreadNum;
int minThreadNum;
ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
Console.WriteLine("最大线程数:", maxThreadNum);
Console.WriteLine("最小空闲线程数:", minThreadNum);
// 函数变量值
int x = 15600;
// 启动第一个任务:计算x的8次方
Console.WriteLine("启动第一个任务:计算的8次方。
", x);
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc1), x);
// 启动第二个任务:计算x的8次方根
Console.WriteLine("启动第二个任务:计算的8次方根。
", x);
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc2), x);
// 等待,直到两个数值都完成计算
while (number1 == -1 || number2 == -1) ;
// 打印计算结果
Console.WriteLine("y() = ", x, number1 + number2);
}
// 启动第一个任务:计算x的8次方
static void TaskProc1(object o)
{
number1 = Math.Pow(Convert.ToDouble(o), 8);
}
// 启动第二个任务:计算x的8次方根
static void TaskProc2(object o)
{
number2 = Math.Pow(Convert.ToDouble(o), 1.0 / 8.0);
}
}回调函数 与 线程 有何区别
普通函数与回调函数的区别:
对普通函数的调用:调用程序发出对普通函数的调用后,程序执行立即转向被调用函数执行,直到被调用函数执行完毕后,再返回调用程序继续执行。
从发出调用的程序的角度看,这个过程为“调用-->等待被调用函数执行完毕-->继续执行”
对回调函数调用:调用程序发出对回调函数的调用后,不等函数执行完毕,立即返回并继续执行。
这样,调用程序执和被调用函数同时在执行。
当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束。
这个过程称为回调(Callback),这正是回调函数名称的由来。
如何创建Worker线程
创建Worker线程首先定义一个线程函数,然后调用AfxBeginThread函数。
AfxBeginThread函数的定义如下:
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize= 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
其中:
pfnThreadProc:线程函数。
pParam:传递给线程函数的参数。
nPriority:线程的优先级。
默认值为THREAD_PRIORITY_NORMAL。
nStackSize:线程的堆栈大小。
默认值为0。
dwCreateFlags:线程的创建标志。
默认值为0,表示线程产生后立即执行。
如果其值为CREATE_SUSPENDED表示线程产生后暂停执行,直到CWinThread::ResumeThread函数被调用。
lpSecurityAttrs:表示线程的安全属性。
默认值为NULL。
函数返回值是一个指向新创建线程对象的指针。
在MFC的THRDCORE.CPP中,AfxBeginThread函数的相关代码如下:
// THRDCORE.CPP
CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
ASSERT(pfnThreadProc != NULL);
CWinThread* pThread = DEBUG_NEW CWinThread(
pfnThreadProc,
pParam);
ASSERT_VALID(pThread);
if (!pThread->CreateThread(
dwCreateFlags|CREATE_SUSPENDED,
nStackSize,
lpSecurityAttrs))
{
pThread->Delete();
return NULL;
}
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1);
return pThread;
}
从MFC代码中可以看出,AfxBeginThread函数首先创建CWinThread对象,然后调用CWinThread::CreateThread函数。
CWinThread::CreateThread函数调用_beginthreadex函数创建线程。
此外,AfxBeginThread和CWinThread::CreateThread还做了一些应用程序框架所需的内部数据的初始化工作。
在MFC的AFXWIN.H中定义了线程函数类型AFX_THREADPROC:
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID);
从定义中可以看出,线程函数返回一个UINT值。
此外,线程函数传递一个LPVOID参数,一般在使用中指向用户自定义的数据结构。
线程函数是由系统调用的,是一个callback函数,所以必须是个全局函数或者是C++类static成员函数,而不能是C++类成员函数。
(1)创建1个基于对话框的应用程序,名称为Demo。
(2)在IDD_DEMO_DIALOG对话框资源中添加控件,如表所示。
类型
ID
标题
Static
IDC_STATIC
数据:
Edit
IDC_DATA
Button
IDC_BEGIN_THREAD
启动线程
(3)在文件中定义线程传递参数的数据结构,代码如下:
// DemoDlg.h
typedef struct THREAD_PARAM
{
HWND hWnd;
int nData;
}_THREAD_PARAM;
(4)在CDemoDlg类中添加成员变量,代码如下:
// DemoDlg.h
protected:
THREAD_PARAM m_ThreadParam;
(5)在CDemoDlg类的构造函数和析构函数中添加如下代码:
// DemoDlg.cpp
CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDemoDlg::IDD, pParent)
{
// ...
m_ThreadParam.nData = 0;
}
(6)在CDemoDlg类的OnInitDialog函数中添加如下代码:
// DemoDlg.cpp
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// …
SetDlgItemInt(IDC_DATA, m_ThreadParam.nData);
return TRUE;
}
(7)在文件中定义线程消息,代码如下:
// DemoDlg.h
#define WM_THREADMSG WM_USER+1
(8)在文件中定义线程函数,代码如下:
// DemoDlg.h
UINT ThreadProc(LPVOID pParam);
// DemoDlg.cpp
UINT ThreadProc(LPVOID pParam)
{
//线程参数
THREAD_PARAM* pThreadParam = (THREAD_PARAM*)pParam;
for (int n = 0; n < 10; n++)
{
Sleep(100);
pThreadParam->nData++;
//向主线程窗口发送消息
::PostMessage(pThreadParam->hWnd, WM_THREADMSG, 0, 0);
}
return 0;
}
(9)在CDemoDlg类中为Button控件添加BN_CLICKED添加消息处理函数,代码如下:
// DemoDlg.cpp
void CDemoDlg::OnBeginThread()
{
m_ThreadParam.hWnd = m_hWnd;
//启动线程
AfxBeginThread(ThreadProc, &m_ThreadParam);
}
(10)在CDemoDlg类中添加自定义消息处理函数,代码如下:
// DemoDlg.h
afx_msg LRESULT OnMsgFunc();
// DemoDlg.cpp
BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)
ON_MESSAGE(WM_THREADMSG, OnMsgFunc)
END_MESSAGE_MAP()
LRESULT CDemoDlg::OnMsgFunc()
{
SetDlgItemInt(IDC_DATA, m_ThreadParam.nData);
return 1;
}queueuserworkitem 线程池异步任务为什么没有被立即执行
那你其他的线程不要独占CPU,在必要的地方添加语句sleep(10)休眠下,就可以释放CPU给其他线程了,你所创建的线程就可以及时执行了。
台湾云服务器去哪里买?国内有没有哪里的台湾云服务器这块做的比较好的?有很多用户想用台湾云服务器,那么判断哪家台湾云服务器好,不是按照最便宜或最贵的选择,而是根据您的实际使用目的选择服务器,只有最适合您的才是最好的。总体而言,台湾云服务器的稳定性确实要好于大陆。今天,云服务器网(yuntue.com)小编来介绍一下台湾云服务器哪里买和一年需要多少钱!一、UCloud台湾云服务器UCloud上市云商,...
2021年6月底,raksmart开发出来的新产品“cloud-云服务器”正式上线对外售卖,当前只有美国硅谷机房(或许以后会有其他数据中心加入)可供选择。或许你会问raksmart云服务器怎么样啊、raksm云服务器好不好、网络速度快不好之类的废话(不实测的话),本着主机测评趟雷、大家受益的原则,先开一个给大家测评一下!官方网站:https://www.raksmart.com云服务器的说明:底层...
ZJI发布了9月份促销信息,针对香港华为云线路物理服务器华为一型提供立减300元优惠码,优惠后香港华为一型月付仅450元起。ZJI是原来Wordpress圈知名主机商家:维翔主机,成立于2011年,2018年9月更名为ZJI,提供中国香港、台湾、日本、美国独立服务器(自营/数据中心直营)租用及VDS、虚拟主机空间、域名注册等业务,商家所选数据中心均为国内访问质量高的机房和线路,比如香港阿里云、华为...
queueuserworkitem为你推荐
1433端口路由器1433端口怎么开启手机区号手机号码安卓应用平台app应用平台有哪些 应用平台哪些qq怎么发邮件用QQ怎样发送文件数据库损坏数据库坏了怎么办安装迅雷看看播放器迅雷看看不能播放,说我尚未安装迅雷看看播放器免费免费建站可以不用钱免费做一个网站吗mate8价格华为mate8什么时候会降价ios系统苹果手机的系统是什么?小米手柄手机用小米手柄能玩什么游戏
中文域名申请 fastdomain inmotionhosting BWH 万网优惠券 论坛空间 本网站服务器在美国 百兆独享 200g硬盘 太原网通测速平台 hkt 如何注册阿里云邮箱 免费私人服务器 个人免费主页 上海电信测速网站 网购分享 备案空间 阿里云官方网站 西安服务器托管 论坛主机 更多