代表和回调 [英] Delegates and Callbacks

查看:87
本文介绍了代表和回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我昨天看到这个解决方案是针对某人的相同主题的问题发布的.

I saw this solution posted yesterday for someone''s question with same subject.

//defines typedefs to make declarations easier
typedef void (__stdcall *CALLBACK1)(int);
typedef void (__stdcall *CALLBACK2)(bool);
//type of the pointer passed to you callback
struct TIMER_PARAM
{
    CALLBACK1 callback1;
    CALLBACK2 callback2;
};
void CALLBACK WaitOrTimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    //get your params
    TIMER_PARAM* pParam = (TIMER_PARAM*)lpParameter;
    if(condition1)
        pParam->callback1(10);
    if(condition2)
        pParam->callback2(true);
}
__declspec(dllexport) void __cdecl StartUpdate(
    CALLBACK1 callback1, CALLBACK2 callback2)
{
    //this pointer will be passed to your callback
    //you will need to delete this pointer somewhere in your code
    //to prevent a memory leak
    TIMER_PARAM* parameters = new TIMER_PARAM;
    parameters->Callback1 = callback1;
    parameters->Callback1 = callback2;
    /*start the timer here*/
    bool success = ::CreateTimerQueueTimer(
        &m_timerHandle,
        NULL,
        TimerFire,
        // will be given as an argument to your timer function
        parameters,
        0,
        1000,
        WT_EXECUTEINTIMERTHREAD);
}

我想知道如何使用System :: Timers :: Timer在C ++/CLI中做类似的事情.

I am wondering how to do a similar thing in C++/CLI using System::Timers::Timer.

aTimer->Elapsed+= gcnew ElapsedEventHandler(TimerFire);


如何将struct对象传递给


How can I pass the struct object to the

static void TimerFire(Object ^sender, ElapsedEventArgs ^e)


有没有一种方法可以在(Object ^ sender)参数中发送TIMER_PARAM结构对象.

或者因为我的类是托管类,所以有一种更优雅的方法将函数指针从C#传递到托管C ++类.


预先感谢您的帮助.


Is there a way to send TIMER_PARAM struct object in (Object ^sender) parameter.

Or since my class is managed class is there a more elegant way to pass function pointers from C# to managed C++ class.


Thanks in advance for your help.

推荐答案

这不是C#和C ++/CLI之间的界限,只有C ++和C ++/CLI之间的界限.

.NET中没有函数指针"(从OOP的角度来看,它是底层的,并不是真正可靠的概念),只有委托.委托实例是一种结构,其中包含方法的某些代码的入口点的集合,每个入口点都具有实现该方法的类/结构实例的值(与"this"指针在每个实例(非静态)方法中传递的相同;此集合称为调用列表,可以通过System.Delegate.GetInvocationList显式调用显式的委托实例来显式遍历.仅对于静态方法"this"不使用.静态和实例方法可以在任何调用列表中混合使用. br/>
C#和C ++/CLI语言之间的区别在这里不是必需的:

C ++/CLI:
This is not a boundary between C# and C++/CLI, there is only a boundary between C++ and C++/CLI.

There are no "function pointers" (which is low-level and not really robust concept in view of OOP) in .NET, there are only delegates. A delegate instance is a structure with includes the collection of entry points of some code of a methods, each with the value of the class/structure instance implementing the method (same as "this" pointers passes in every instance (non-static) method; this collection is called invocation list and can be traversed explicitly via invocation of the delegate instance of explicitly through System.Delegate.GetInvocationList. Only for a static method "this" is not used. Static and instance methods can mix up in any invocation list.

Difference between C# and C++/CLI languages is not essential here:

C++/CLI:
aTimer->Elapsed += gcnew ElapsedEventHandler(TimerFire);

//...

// this is no point to use static here (surprize!),
// with static, you loose access to the instance (via "this"), so write non-static.
void TimerFire(Object ^sender, ElapsedEventArgs ^e) { /*...*/ }



C#:



C#:

void TimerFire(Object sender, ElapsedEventArgs e) { /* ... */ }

//...

aTimer->Elapsed += new TimerFire;

//same as:
aTimer2->Elapsed += new ElapsedEventHandler(TimerFire);

//even better
aTimer3->Elapsed += delegate(object sender, ElapsedEventArgs eventArgs) {
    //TimerFire is not needed, call any code here,
    //it may or may not use sender and eventArgs
};

//the most convenient way is using lambda:
aTimer4->Elapsed += (sender, eventArgs) => {
    //TimerFire is not needed, call any code here,
    //it may or may not use sender and eventArgs
    //you don't even need to argument types:
    //they are inferred from even type (so called type inference)
};



您可以以任何组合使用这些声明:在C#上编写实现,然后以C ++/CLI或相反的方式添加到调用列表中.
最后的通知:绝对避免使用计时器.请改用线程!

—SA



You can use these declarations in any combination: write implementation on C# and add to the invocation list in C++/CLI or the other way around.

A final notice: avoid using timers by all means. Use threads instead!

—SA


这篇关于代表和回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆