在C++/CLI中将参数传递给任务?

Bez*_*sek 11 action arguments c++-cli task

我在Visual Studio 2012中有C#的代码.

public Task SwitchLaserAsync(bool on)
{
   return Task.Run(new Action(() => SwitchLaser(on)));
}
Run Code Online (Sandbox Code Playgroud)

这将执行SwitchLaser方法(类的公共非静态成员MyClass)作为参数bool on的任务.

我想在托管C++/CLI中做类似的事情.但我无法找到如何运行任务的任何方法,该任务将执行采用一个参数的成员方法.

目前的解决方案是这样的:

Task^ MyClass::SwitchLaserAsync( bool on )
{
    laserOn = on;   //member bool 
    return Task::Run(gcnew Action(this, &MyClass::SwitchLaserHelper));
}
Run Code Online (Sandbox Code Playgroud)

执行SwitchLaserHelper功能:

void MyClass::SwitchLaserHelper()
{
     SwitchLaser(laserOn);
}
Run Code Online (Sandbox Code Playgroud)

必须有一些像C#中的解决方案而不是创建辅助函数和成员(这不是线程安全的).

Ben*_*igt 12

目前还没有办法做到这一点.

在C#中你有一个闭包.编写C++/CLI编译器时,仍在讨论C++中闭包的标准化语法.值得庆幸的是,Microsoft选择等待并使用标准的lambda语法,而不是引入另一种独特的语法.不幸的是,这意味着该功能尚不可用.如果是,它将看起来像:

gcnew Action([on](){ SwitchLaserHelper(on) });
Run Code Online (Sandbox Code Playgroud)

当前线程安全解决方案是执行C#编译器所做的事情 - 将辅助函数和数据成员放入当前类中,而不是放入嵌套子类型中.当然this,除了本地变量之外,你还需要保存指针.

ref class MyClass::SwitchLaserHelper
{
    bool laserOn;
    MyClass^ owner;

public:
    SwitchLaserHelper(MyClass^ realThis, bool on) : owner(realThis), laserOn(on) {}
    void DoIt() { owner->SwitchLaser(laserOn); }
};

Task^ MyClass::SwitchLaserAsync( bool on )
{
    return Task::Run(gcnew Action(gcnew SwitchLaserHelper(this, on), &MyClass::SwitchLaserHelper::DoIt));
}
Run Code Online (Sandbox Code Playgroud)

C++ lamdba语法将为您创建该助手类(目前它适用于本机lambda,但尚未用于托管类).


Ðаn*_*Ðаn 5

这是我今天下午编写的通用代码,可能会有所帮助(尽管它与这个问题并不完全匹配)。也许这会对下一个偶然发现这个问题的人有所帮助。

generic<typename T, typename TResult>
ref class Bind1
{
    initonly T arg;
    Func<T, TResult>^ const f;
    TResult _() { return f(arg); }

public:
    initonly Func<TResult>^ binder;
    Bind1(Func<T, TResult>^ f, T arg) : f(f), arg(arg) {
        binder = gcnew Func<TResult>(this, &Bind1::_);
    }
};

ref class Binder abstract sealed // static
{
public:
    generic<typename T, typename TResult>
    static Func<TResult>^ Create(Func<T, TResult>^ f, T arg) {
        return (gcnew Bind1<T, TResult>(f, arg))->binder;
    }
};
Run Code Online (Sandbox Code Playgroud)

用法是

const auto f = gcnew Func<T, TResult>(this, &MyClass::MyMethod);
return Task::Run(Binder::Create(f, arg));
Run Code Online (Sandbox Code Playgroud)


小智 3

这是有效的答案..已经测试过..将参数(int)传递给操作sampleFunction。

#include "stdafx.h"
#include "CLRSamples.h"

using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;
using namespace System::Collections;
using namespace System::Collections::Generic;

void CLRSamples::sampleFunction(Object^ number)
{
    Console::WriteLine(number->ToString());
    Thread::Sleep((int)number * 100);
}

void CLRSamples::testTasks()
{
    List<Task^>^ tasks = gcnew List<Task^>();

    for (int i = 0; i < 10; i++)
    {
        tasks->Add(Task::Factory->StartNew((Action<Object^>^)(gcnew Action<Object^>(this, &CLRSamples::sampleFunction)), i));
    }

    Task::WaitAll(tasks->ToArray());

    Console::WriteLine("Completed...");
}

int main(array<System::String ^> ^args)
{
    CLRSamples^ samples = gcnew CLRSamples();
    samples->testTasks();

    Console::Read();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)