2012-10-25 23 views
10

मैं दृश्य स्टूडियो 2012.सी ++/सीएलआई में कार्य करने के लिए एक तर्क पास?

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

इस पर तर्क bool के साथ एक कार्य के रूप में (एक वर्ग MyClass की सार्वजनिक nonstatic सदस्य) SwitchLaser विधि निष्पादित करेंगे में के लिए सी # इस कोड है।

मैं प्रबंधित सी ++/सीएलआई में कुछ ऐसा करना चाहता हूं। लेकिन मैं किसी कार्य को चलाने का तरीका खोजने में सक्षम नहीं हूं, जो एक पैरामीटर लेने वाले सदस्य विधि को निष्पादित करेगा। (

void MyClass::SwitchLaserHelper() 
{ 
    SwitchLaser(laserOn); 
} 

सी # में जैसे कुछ समाधान होना चाहिए और सहायक कार्य करता है और सदस्यों को बनाने के लिए नहीं इस threadsafe नहीं है:

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

SwitchLaserHelper समारोह के कार्यान्वयन:

वर्तमान समाधान इस तरह है)।

उत्तर

10

ऐसा करने का कोई तरीका नहीं है।

सी # में आपके पास बंद है। जब आपका सी ++/सीएलआई कंपाइलर लिखा गया था, तो सी ++ में बंद होने के लिए मानकीकृत वाक्यविन्यास पर अभी भी चर्चा की जा रही थी। शुक्र है, माइक्रोसॉफ्ट ने अभी तक एक और अद्वितीय वाक्यविन्यास पेश करने के बजाय मानक लैम्ब्डा वाक्यविन्यास का इंतजार और उपयोग करना चुना है। दुर्भाग्यवश, इसका मतलब है कि सुविधा अभी तक उपलब्ध नहीं है। जब यह होता है, यह कुछ ऐसी दिखाई देगी:

gcnew Action([on](){ SwitchLaserHelper(on) }); 

वर्तमान threadsafe समाधान क्या सी # संकलक करता है करने के लिए है - सहायक समारोह और डेटा सदस्यों वर्तमान वर्ग में नहीं डाल दिया है, लेकिन एक नेस्टेड उप-प्रकार में। बेशक आपको अपने स्थानीय चर के अलावा 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)); 
} 

सी ++ lamdba वाक्य रचना बस उस सहायक वर्ग पैदा करेगा के लिए आप (वर्तमान में यह देशी lambdas के लिए कामयाब रहे लोगों के लिए काम करता है, लेकिन अभी तक नहीं)।

+0

उत्तर के लिए धन्यवाद। यह स्पष्ट है कि प्रबंधित कोड में लैम्ब्डा समर्थित नहीं है। फिर भी मैं सहायक वर्गों के निर्माण से बचना चाहता हूं। प्रलेखन में जो मैंने पाया है वह प्रबंधित C++ के लिए क्लास एक्शन है। यह एक तर्क के साथ एक समारोह करने में सक्षम होना चाहिए, लेकिन मैं इसका उपयोग करने में सक्षम नहीं था और विशेष रूप से कार्य :: रन विधि (या किसी भी तरह से कार्य वर्ग के साथ इसका उपयोग करें) के साथ। क्या एक सहायक वर्ग या सहायक तरीके के बिना कोई समाधान है? – Bezousek

+0

@ बेज़ौस्क: 'कार्य :: रन' को 'एक्शन' प्रतिनिधि की आवश्यकता होती है। नहीं, एक 'एक्शन ' एक ही प्रकार का नहीं है। क्लोजर एक सहायक वर्ग के साथ लागू किया जाता है। यही कारण है कि सी # कंपाइलर आपके प्रश्न में आपके उदाहरण कोड से बनाता है, और यदि प्रबंधित लैम्ब्डा सुविधाओं को जोड़ा जाता है तो सी ++/सीएलआई कंपाइलर किसी दिन ऐसा करेगा। –

3

यहां जेनेरिक कोड है जिसे मैंने आज दोपहर लिखा था जो मदद कर सकता है (हालांकि यह इस प्रश्न के लिए सटीक मिलान नहीं है)। शायद यह अगले व्यक्ति की मदद करेगा जो इस प्रश्न पर ठोकर खाएगा।

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; 
    } 
}; 

उपयोग (retuns void)

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

मैं एक ऐसी ही समस्या थी जब मैं एक तरीका है जिसके एक मूल्य वापस नहीं करता है को क्रियान्वित करने के लिए एक कार्य के लिए एक पैरामीटर प्रदान करने के लिए करना चाहता था है। उस Func<T, TResult> के कारण कोई विकल्प नहीं था जिसका मैं उपयोग कर सकता था। अधिक जानकारी के लिए, कृपया पृष्ठ Using void return types with new Func देखें।

तो मैं एक समाधान है, जहां मैं एक सहायक वर्ग

template <typename T> 
ref class ActionArguments 
{ 
public: 
    ActionArguments(Action<T>^ func, T args) : m_func(func), m_args(args) {}; 
    void operator()() { m_func(m_args); }; 

private: 
    Action<T>^ m_func; 
    T m_args; 
}; 

जो Action<T> प्रतिनिधि उपयोग कर रहा है एक विधि एक एकल पैरामीटर है और एक मूल्य वापस नहीं करता है कि संपुटित करने के लिए बनाया के साथ समाप्त हो गया।

मैं तो इस सहायक वर्ग एक के बाद रास्ते में

ref class DisplayActivationController 
{ 
public: 
    DisplayActivationController(); 

    void StatusChanged(EventArgs^ args) { }; 
} 


Action<EventArgs^>^ action = 
    gcnew Action<EventArgs^>(this, &DisplayActivationController::StatusChanged); 
ActionArguments<EventArgs^>^ action_args = 
    gcnew ActionArguments<EventArgs^>(action, args); 
Threading::Tasks::Task::Factory-> 
    StartNew(gcnew Action(action_args, &ActionArguments<EventArgs^>::operator())); 

दृष्टिकोण का उपयोग सहायक वर्ग शायद सबसे सुरुचिपूर्ण समाधान नहीं है का प्रयोग करेंगे, लेकिन सबसे अच्छा एक मैं मिल सकता है C++/CLI में इस्तेमाल किया जा रहा है जो लैम्ब्डा अभिव्यक्तियों का समर्थन नहीं करता है।

संबंधित मुद्दे