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给其他线程了,你所创建的线程就可以及时执行了。
ZJI发布了一款7月份特别促销独立服务器:香港邦联四型,提供65折优惠码,限量30台(每用户限购1台),优惠后每月520元起。ZJI是原来Wordpress圈知名主机商家:维翔主机,成立于2011年,2018年9月启用新域名ZJI,提供中国香港、台湾、日本、美国独立服务器(自营/数据中心直营)租用及VDS、虚拟主机空间、域名注册等业务。下面列出这款服务器的配置信息。香港邦联四型CPU:2*E5-2...
cyun怎么样?cyun蓝米数据是一家(香港)藍米數據有限公司旗下品牌,蓝米云、蓝米主机等同属于该公司品牌。CYUN全系列云产品采用KVM架构,SSD磁盘阵列,优化线路,低延迟,高稳定。目前,cyun推出的香港云服务器性价比超高,香港cn2 gia云服务器,1核1G1M/系统盘+20G数据盘,低至29元/月起;香港多ip站群云服务器,16个ip/4核4G仅220元/月起,希望买香港站群服务器的站长...
搬瓦工和Vultr哪个好?搬瓦工和Vultr都是非常火爆的国外VPS,可以说是国内网友买的最多的两家,那么搬瓦工和Vultr哪个好?如果要选择VPS,首先我们要考虑成本、服务器质量以及产品的售后服务。老玩家都知道目前在国内最受欢迎的国外VPS服务商vultr和搬瓦工口碑都很不错。搬瓦工和Vultr哪个稳定?搬瓦工和Vultr哪个速度快?为了回答这些问题,本文从线路、速度、功能、售后等多方面对比这两...
queueuserworkitem为你推荐
赵雨润电影《奇迹世界》详细剧情介绍简体翻译成繁体简体字怎么换成繁体。。?怎么样免费装扮qq空间要怎么免费装扮QQ空间!伪静态怎么做伪静态?1433端口怎么去看1433端口今日热点怎么删除怎样删除实时热点镜像文件是什么什么叫镜像文件,作用是什么?怎么上传音乐怎么上传音乐?gbk编码表GB GBK utf8码的区别微信电话本怎么用微信电话本短信管理功能怎么用?
虚拟主机测评 t牌 免费主机 512av gomezpeer 174.127.195.202 火车票抢票攻略 网站实时监控 web服务器架设软件 hnyd 上海域名 建立邮箱 怎么测试下载速度 中国电信测网速 tna官网 33456 东莞服务器 web服务器搭建 万网空间管理 个人免费邮箱 更多