当前位置: 首页 > news >正文

windows C++-在启用 COM 的应用程序中使用并发(三)

完整代码

 以下代码演示完整示例,其中使用并行算法和异步代理调用计算斐波纳契数的脚本过程。

// parallel-scripts.cpp
// compile with: /EHsc #include <agents.h>
#include <ppl.h>
#include <array>
#include <sstream>
#include <iostream>
#include <atlsafe.h>// TODO: Change this path if necessary.
#import "C:\windows\system32\msscript.ocx"using namespace concurrency;
using namespace MSScriptControl;
using namespace std;// An exception-safe wrapper class that manages the lifetime 
// of the COM library in a given scope.
class CCoInitializer
{
public:explicit CCoInitializer(DWORD dwCoInit = COINIT_APARTMENTTHREADED): _coinitialized(false){// Initialize the COM library on the current thread.HRESULT hr = CoInitializeEx(NULL, dwCoInit);if (FAILED(hr))throw hr;_coinitialized = true;}~CCoInitializer(){// Free the COM library.if (_coinitialized)CoUninitialize();}
private:// Flags whether COM was properly initialized.bool _coinitialized;// Hide copy constructor and assignment operator.CCoInitializer(const CCoInitializer&);CCoInitializer& operator=(const CCoInitializer&);
};// Calls a procedure in an IScriptControl object.
template<size_t ArgCount>
_variant_t RunScriptProcedure(IScriptControlPtr pScriptControl, _bstr_t& procedureName, array<_variant_t, ArgCount>& arguments)
{// Create a 1-dimensional, 0-based safe array.SAFEARRAYBOUND rgsabound[]  = { ArgCount, 0 };CComSafeArray<VARIANT> sa(rgsabound, 1U);// Copy the arguments to the safe array.LONG lIndex = 0;for_each(begin(arguments), end(arguments), [&](_variant_t& arg) {HRESULT hr = sa.SetAt(lIndex, arg);if (FAILED(hr))throw hr;++lIndex;});//  Call the procedure in the script.return pScriptControl->Run(procedureName, &sa.m_psa);
}// Computes multiple Fibonacci numbers in parallel by using 
// the parallel_for algorithm.
HRESULT ParallelFibonacci(IScriptControlPtr pScriptControl)
{try {parallel_for(10L, 20L, [&pScriptControl](LONG lIndex) {// Enable COM for the lifetime of the task.CCoInitializer coinit(COINIT_MULTITHREADED);// Call the helper function to run the script procedure.array<_variant_t, 1> args = { _variant_t(lIndex) };_variant_t result = RunScriptProcedure(pScriptControl, _bstr_t("fib"), args);// Print the result.wstringstream ss;         ss << L"fib(" << lIndex << L") = " << result.lVal << endl;wcout << ss.str();});}catch (HRESULT hr) {return hr;}return S_OK;
}// A basic agent that calls a script procedure to compute the 
// nth Fibonacci number.
class FibonacciScriptAgent : public agent
{
public:FibonacciScriptAgent(IScriptControlPtr pScriptControl, ISource<LONG>& source): _pScriptControl(pScriptControl), _source(source) { }public:// Retrieves the result code.HRESULT GetHRESULT() {return receive(_result);}protected:void run(){// Initialize the COM library on the current thread.CoInitializeEx(NULL, COINIT_MULTITHREADED);// Read values from the message buffer until // we receive the sentinel value.      LONG lValue;while ((lValue = receive(_source)) != Sentinel){try {// Call the helper function to run the script procedure.array<_variant_t, 1> args = { _variant_t(lValue) };_variant_t result = RunScriptProcedure(_pScriptControl, _bstr_t("fib"), args);// Print the result.wstringstream ss;         ss << L"fib(" << lValue << L") = " << result.lVal << endl;wcout << ss.str();}catch (HRESULT hr) {send(_result, hr);break;    }}// Set the result code (does nothing if a value is already set).send(_result, S_OK);// Free the COM library.CoUninitialize();// Set the agent to the finished state.done();}public:// Signals the agent to terminate.static const LONG Sentinel = 0L;private:// The IScriptControl object that contains the script procedure.IScriptControlPtr _pScriptControl;// Message buffer from which to read arguments to the // script procedure.ISource<LONG>& _source;// The result code for the overall operation.single_assignment<HRESULT> _result;
};// Computes multiple Fibonacci numbers in parallel by using 
// asynchronous agents.
HRESULT AgentFibonacci(IScriptControlPtr pScriptControl)
{// Message buffer to hold arguments to the script procedure.unbounded_buffer<LONG> values;// Create several agents.array<agent*, 3> agents = {new FibonacciScriptAgent(pScriptControl, values),new FibonacciScriptAgent(pScriptControl, values),new FibonacciScriptAgent(pScriptControl, values),};// Start each agent.for_each(begin(agents), end(agents), [](agent* a) {a->start();});// Send a few values to the agents.send(values, 30L);send(values, 22L);send(values, 10L);send(values, 12L);// Send a sentinel value to each agent.for_each(begin(agents), end(agents), [&values](agent*) {send(values, FibonacciScriptAgent::Sentinel);});// Wait for all agents to finish.agent::wait_for_all(3, &agents[0]);// Determine the result code.HRESULT hr = S_OK;for_each(begin(agents), end(agents), [&hr](agent* a) {HRESULT hrTemp;if (FAILED(hrTemp = reinterpret_cast<FibonacciScriptAgent*>(a)->GetHRESULT())){hr = hrTemp;}});// Clean up.for_each(begin(agents), end(agents), [](agent* a) {delete a;});return hr;
}int wmain()
{HRESULT hr;// Enable COM on this thread for the lifetime of the program.   CCoInitializer coinit(COINIT_MULTITHREADED);// Create the script control.IScriptControlPtr pScriptControl(__uuidof(ScriptControl));// Set script control properties.pScriptControl->Language = "JScript";pScriptControl->AllowUI = TRUE;// Add script code that computes the nth Fibonacci number.hr = pScriptControl->AddCode("function fib(n) { if (n<2) return n; else return fib(n-1) + fib(n-2); }" );if (FAILED(hr))return hr;// Test the script control by computing the 15th Fibonacci number.wcout << L"Main Thread:" << endl;long n = 15;array<_variant_t, 1> args = { _variant_t(n) };_variant_t result = RunScriptProcedure(pScriptControl, _bstr_t("fib"), args);// Print the result.wcout << L"fib(" << n << L") = " << result.lVal << endl;// Use the parallel_for algorithm to compute multiple // Fibonacci numbers in parallel.wcout << endl << L"Parallel Fibonacci:" << endl;if (FAILED(hr = ParallelFibonacci(pScriptControl)))return hr;// Use asynchronous agents to compute multiple // Fibonacci numbers in parallel.wcout << endl << L"Agent Fibonacci:" << endl;if (FAILED(hr = AgentFibonacci(pScriptControl)))return hr;return S_OK;
}

该示例生成以下示例输出。

Main Thread:
fib(15) = 610Parallel Fibonacci:
fib(15) = 610
fib(10) = 55
fib(16) = 987
fib(18) = 2584
fib(11) = 89
fib(17) = 1597
fib(19) = 4181
fib(12) = 144
fib(13) = 233
fib(14) = 377Agent Fibonacci:
fib(30) = 832040
fib(22) = 17711
fib(10) = 55
fib(12) = 144

http://www.mrgr.cn/news/49019.html

相关文章:

  • 『网络游戏』摄像机跟随【31】客
  • Python快速编程小案例--逢7拍手小游戏
  • 【LeetCode】动态规划—96. 不同的二叉搜索树(附完整Python/C++代码)
  • jvm介绍
  • 【ICPC】The 2024 ICPC Kunming Invitational Contest J
  • Kubernetes 实战之旅:从 0 到 1 搭建完整集群的奇妙征程
  • 计算机毕设选题推荐【人工智能专业】
  • [论文精读]Active and Semi-Supervised Graph Neural Networks for Graph Classification
  • 交叉编译--目标平台aarch64 ubuntu 22.04
  • 【AI绘画】Midjourney进阶:三分线构图详解
  • (全网独家)面试要懂运维真实案例:HDFS重新平衡(HDFS Balancer)没触发问题排查
  • 【C++】map和set的介绍以及用法
  • 记录使用appium+夜神模拟器测试多设备时selenium和appium版本不兼容带来的问题
  • 限界上下文(Bounded Context)
  • 开发指南072-模型定义
  • 【Power Query】List.Max List.Min
  • unpacking
  • 软考高级软件架构师论文——论Web系统的测试技术及其应用
  • 力扣刷题之3158.求出出现两次数字的XOR值
  • javaScripts 知识点一 (面试题)