本地C++中的函数指针,提供了一种异步执行代码的机制,你可以存储一个函数指针,而在以后有需要的时候及时地调用,这通常用于把某算法与实现代码分开来,如在搜索中比较对象。另外,它也可在不同的线程中调用,以实现真实的异步编程。以下是一个ThreadPool类的简单示例,允许你排列一系列的函数指针,并在工作者线程中执行。
class ThreadPool
...{
public:
![]()
template <typename T>
static void QueueUserWorkItem(void (T::*function)(), T* object)
...{
typedef std::pair<void (T::*)(), T*> CallbackType;
std::auto_ptr<CallbackType> p(new CallbackType(function, object));
![]()
if (::QueueUserWorkItem(ThreadProc<T>,
p.get(),
WT_EXECUTEDEFAULT))
...{
//ThreadProc负责删除pair.
p.release();
}
else
...{
AtlThrowLastWin32();
}
}
![]()
private:
![]()
template <typename T>
static DWORD WINAPI ThreadProc(PVOID context)
...{
typedef std::pair<void (T::*)(), T*> CallbackType;
std::auto_ptr<CallbackType> p(static_cast<CallbackType*>(context));
(p->second->*p->first)();
return 0;
}
![]()
ThreadPool();
};
![]()
在C++中使用线程池是简单兼自然的。
class Service
...{
public:
![]()
void AsyncRun()
...{
ThreadPool::QueueUserWorkItem(Run, this);
}
![]()
void Run()
...{
//其他代码
}
}
很明显,ThreadPool类是非常受限的,它只能接受特定的函数指针,这只是示例本身而不是C++本身的局限性。
当C++程序员想要实现或得到用于异步编程的丰富库函数时,带着有此内置支持的CLR来了。"代理"与函数指针非常类似,除了针对的目标及方法属于的类型(其不能决定是否一个代理可以绑定于一个给定的方法);只要类型匹配,方法就能被代理,并在以后调用,与上面使用C++模板来实现允许接受任何类成员函数的例子比较,这在思想上是相似的。当然,代理还提供了更多且极其有用的间接函数调用的机制,以下是在C++/CLI中定义一个代理类型的示例:
delegate void Function();
使用代理也非常直截了当。
ref struct ReferenceType
...{
void InstanceMethod() ...{}
static void StaticMethod() ...{}
};
![]()
//创建代理并绑定到成员函数的实例
Function^ f = gcnew Function(gcnew ReferenceType, ReferenceType::InstanceMethod);
![]()
//也可绑定到静态成员函数,并结合几个代理形成代理链
f += gcnew Function(ReferenceType::StaticMethod);
![]()
//调用函数
f();
结束语
关于C++/CLI,真是说上几天也说不完,新的语言设计提供了空前的威力和很少有的"优雅"语法,并且可在不牺牲简洁性、编程效率、执行效率的情况下,完全地使用C++来编写丰富的 .NET应用程序。