A. 委托为什么叫回调
回调(callback)函数复是Windows编程的一个重要部制分。如果您具备C或C++编程背景,应该就曾在许多Windows API中使用过回调。Visual Basic添加了AddressOf关键字后,开发人员就可以利用以前一度受到限制的API了。回调函数实际上是方法调用的指针,也称为函数指针,是一个非常强大的编程特性。.NET以委托的形式实现了函数指针的概念。它们的特殊之处是,与C函数指针不同,.NET委托是类型安全的。这说明,C中的函数指针只不过是一个指向存储单元的指针,我们无法说出这个指针实际指向什么,像参数和返回类型等就更无从知晓了。如本章所述,.NET把委托作为一种类型安全的操作。本章后面将学习.NET如何将委托用作实现事件的方式。
详情咨询
http://book.csdn.net/bookfiles/829/
B. c#中委托怎么用
委托主要用于.NET Framework中的事件处理程序和回调函数,它是事件的基础。
委托的作用类似于c++中函数指针的作用。不同的是,委托实例独立于它所封装的方法的类,并且方法类型与委托的类型是兼容的。函数指针只能引用静态函数,而委托可以应用静态和实例方法。
所有委托都是继承自System.Delegate类,并且有一个调用列表。调用委托时所执行的方法都被存放在这样的一个连接列表中。
使用delegate关键字可以声明一个委托。通过将委托与命名方法或匿名方法关联,可以对委托进行实例化。为了与命名方法一起使用,委托必须用具有可接受签名的方法进行实例化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
//声明一个委托
delegate int Mydelegate();
class Program
{
static void Main(string[] args)
{
test p = new test();
//将委托指向非静态方法
Mydelegate m = new Mydelegate(p.InstanceMethod);
//调用非静态方法
m();
//将委托指向静态方法
m = new Mydelegate(test.StaticMethod);
//调用静态方法
m();
Console.Read();
}
}
public class test
{
public int InstanceMethod()
{
Console.WriteLine("正在调用非静态方法InstanceMethod()....");
return 0;
}
static public int StaticMethod()
{
Console.WriteLine("正在调用静态方法StaticMethod()。。。。");
return 0;
}
}
}
C. 请教C#回调函数的调用问题
其实在C#语言中,如果不考虑unsafe编程的情况下,C#已经不存在指针了!但是有一种情况很特殊——我们需要实现将一个成员方法(函数是不规则的称呼,面向对象中只有成员方法,没有函数的概念了)做为一个参数传入到另一个方法。
当然,在C/CPP中我们存在指针,把函数(或成员方法,面向过程语言或支持面向过程语言中存在函数或过程的概念)指针做为参数传递即可——这是一种典型的“传址”引用的方式,在C#没有指针的情况下想完成一个传址引用,ref/out只能传递参数变量,并不能将方法转换成地址传入另一个方法的参数(方法参数化),怎么办——委托!
其实说白了,委托就是一种特殊的“代理”形式,把一个成员方法代理成一个变量(delegate变量),可以直接进行调用(根据委托形式,可以找到委托中代理的具体成员方法)!
回调就是一个委托的特殊形式,如果说委托着重于说明“代理”调用的话,而回调则是着重说明成员方法的参数化(指针特性)。
很多个认为一个完整的委托是要有委托(delegate声明)和代理的方法(真正执行的方法),然后要求其形式完全一致,但是,由于C#语法糖的存在,我们还种一种特殊形式的委托——匿名委托!很多人很奇怪,为什么方法名参做为一个参数呢?其实就是匿名委托,传入并非方法名,而是方法名的匿名委托(委托没有名字,所以只需要传入方法名即可)!
不要以为你回调函数你传入的是方法名——因为匿名委托的原因,这个方法名被自动包装成了一个没有名字的委托!看起来是传入方法名——其实原理根本不是那么回事!
当然即使你理解成方法名也可以,但只是一种错误的理解。因为他与常规的委托着重点不同,委托着重于代理执行,用于编译时确认成员方法。而回调则是运行时确定成员方法,着重于指针形式,所以匿名委托足以使用,能让你更容易理解回调函数(好象是被调用对象在执行期间又重新调用了调用对象的某个方法,所以叫回调——执行绪再次调用主体成员方法——就是A对象调用了B对象的BMethod方法,而BMethod方法需要再调用A对象的某个成员方法AMethod,那么传入Amethod方法的匿名委托就是回调,当然如果C对象是A对象的一个属性或成员时,调用C对象的方法也是回调——A的某个对象属性的成员方法)
回调如果你把CallBack参数当做一个成员方法时,那么,回调方法的理解也会变得超简单。
D. 请问委托异步回调函数是否可以获得执行后的内容(跨项目)
static void process_Callback(IAsyncResult result)
{
int value = Convert.ToInt32(ar.AsyncState);
AsyncResult aResult = (AsyncResult)ar;
putNewWeibo temp = (putNewWeibo)aResult.AsyncDelegate;
int result = temp.EndInvoke(ar);
}
E. 举例:关于回调函数(callback function)格式参数
回调函数其实是一种委托,所以没有必然的规定,创建一个符合指定的委托的函数,然后由这个函数创建回调所指定的委托作为参数就可以了。
要具体的解释的话,请楼主指明应用的场合吧。
--------------------------------------------
那个是事件,不过也是委托的一种。回调其实用的也是委托。
比如,button的Click事件引发时,它要求的是一个 EventHandler 的定义,其实这里的 EventHandler 就是一个委托是定义。它的定义格式是
void EventHanlder(object sender,EventArgs e)
这就约定了Button的Click事件的处理程序的标准格式了,也就是用来处理这个事件的函数必须符合这样的参数和返回条件。
当Button控件决定要引发这个事件的时候,它就不用去考虑具体来接收这个事件的函数是怎么实现、是什么参数类型了,因为在它看来,Click事件的处理函数都符合EventHandler这个委托的定义(实际上都已经是EventHandler这个委托的实例了),所以它便直接Invoke调用即可,不需要再去考虑其它因素。
事实上,如果不用委托,那么事件是无法实现的,因为作为调用方,没有它已知的公用约束的话,它是无法预知它所要调用的处理函数的参数和返回值,在一定程度上说这样的调用是无法实现的。
给楼主一篇博文参考:
http://www.cnblogs.com/birdshover/archive/2008/01/07/1029471.html
F. 如何实现DLL里面的回调函数
在进一步执行实现前,请查看 EnumWindows 函数的签名。 EnumWindows 具有以下签名:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
此函数需要回调的线索之一是存在 lpEnumFunc 参数。 经常可以看到在采用指向回调函数的指针的参数名称中 lp(长指针)前缀与 Func 后缀结合在一起。 有关 Win32 函数的文档,请参阅 Microsoft Platform SDK。
创建托管回调函数。 此示例声明一个名为 CallBack 的委托类型,该类型采用两个参数(hwnd 和 lparam)。 第一个参数是窗口的句柄;第二个参数是应用程序定义的。 在此版本中,这两个参数都必须是整数。
回调函数通常返回非零值来指示成功,返回零值来指示失败。 此示例将返回值显式设置为 true 以继续进行枚举。
创建一个委托,并将其作为参数传递到 EnumWindows 函数。 平台调用自动将该委托转换为常见的回调格式。
确保在回调函数完成其工作之前,垃圾回收器不会回收委托。 当将委托作为参数传递,或传递作为字段包括到结构中的委托时,在调用期间不会对其进行回收。 因此,正如下面的枚举示例一样,调用返回并不再需要托管调用方执行任何其他操作之前,回调函数完成其工作。
G. 委托,事件和回调函数这3者之间到底是什么关
这是因为你的回调委托作用域问题。在回调时,委托已经被回收了 所谓成员变版量: class test{ public delegate a; public void foo(){ private delegate b; } } 像这种情况权,b委托的作用域只在foo()函数里面,如果你让b被非托管代码回调,当foo执行完后,非托管代码回调时很可能b已被回收了。所以出现这个错。 a委托是test类的成员变量,它是可以一直保持的,除非你对test进行了析构。 也可以使用static的变量。 也就是说,尽量扩大你的委托的作用域,保证在回调是它不会被自动回收就行了。
H. 问c# 委托异步调用的回调函数问题
这个来我查的资料。《CLR Via c#》3描述是,当自BeginInvoke调用完成以后,方法会被放进队列,CLR线程池会激活一个线程,来调用方法,方法执行完毕以后,如果没有回调函数,线程会直接返回到线程池里,但是存在回调函数,这个线程会继续调用回调函数。 所以 我觉得是调用你实际方法的CLR上的线程。
I. C#中委托如何使用
1.委托概述
委托是C#中新加入的一个类型,可以把它想作一个和Class类似的一种类型,和使用类相似,使用一个委托时,需要两个步骤,首先你要定义一个委托,就像是定义一个类一样;然后,你可以创建一个或多个该委托的实例。
定义一个委托的语法是这样的:
[public/protected/private] delegate returnType delegateName(paramtype param1,…)
这是我自己写的,看起来好像有点怪怪的,我来解释一下,private/protected/private是限定词,就不多说了,delegate是申明一个委托的关键词,returnType是一个返回类型,delegateName是一个你给委托起的名字,你可以写任何一个你喜欢的名字,paramtype param1…这个是参数列表。说了这么多可能看起来还是不是很好理解,我是这样认为的,实用点来讲,委托定义就是在一个函数定义中间加入一个delegate的关键词。它的作用类似于你申明一个类:
public class ClassName {…}
创建一个委托的实例:
[public/protected/private] delegateName deleInstanceName = new delegateName(MethodName)
这个类似于实例化一个类,public ClassName instancename = new ClassName(…),这里有个要注意的地方,即MethodName方法要和delegateName的签名一致。什么是签名一致,就是说MethodName的参数列表,返回值要分别和returnType、(paramtype param1,…)一致。举个例子来说明下:
public delegate string DelegateDemo(string name, int age);
比如我们如上定义了一个委托,就写法来说,其实就是在函数 string DelegateDemo(string name, int age)前面加了一个delegate的关键字,下面我们来用创建一个函数:
public string AgentDemo(string name, int age)
{
string rev = “”;
…
return rev;
}
这个函数是做参数传递给一个DelegateDemo实例的,接下来创建一个DelegateDemo的实例:
DelegateName instanceDemo = new DelegateName(AgentDemo);
这时要说到一致了,即AgentDemo和声明委托时的DelegateDemo(我们姑且将delegate去掉)这两个函数的返回值,参数列表要相同。终于说完了,不知道看的人明不明白。
接下来,我们可以使用这个委托了(调用一个委托),如下:
string name = “cshape”;
int age = 20;
instanceDemo(name, age);
当instanceDemo执行时,会执行AgentDemo函数,instanceDemo相当于C里的一个函数指针,现在这个指针指向AgentDemo的函数入口地址。
2.多点委托
前面提到的委托都只包含对一个方法的调用,如果需要调用多个方法,需要多次显示的调用这个委托,我们还有另的选择,我们可以让一个委托中包含多个方法,这样我们一次显示调用委托,就可以按照顺序连续的调用多个方法。看下面的例子:
public delegate void MultiDelegate(string name);
public void AgentDemo1(string str)
{
Console.WriteLine(str + “this is AgentDemo1\n”);
}
public void AgentDemo2(string s)
{
Console.WriteLine(s + “this is AgentDemo2\n”);
}
MultiDelegate multiDemo = new MultiDelegate(AgentDemo1);
multiDemo += new MultiDelegate(AgentDemo2);
multiDemo(“multiDemo test :”);
输出的结果应该是:
multiDemo test :this is AgentDemo1
mutliDemo test :this is AgentDemo2
可以看到我们一次显示的调用一个委托,它顺序的(按照你添加方法的顺序)执行了方法AgentDemo1和AgentDemo2。这里要注意的有几点:
● 委托支持 +=,-=这样的运算符,对应为添加或去掉一个方法
● 多点委托不可以定义有返回值,因为无法处理多个方法的返回值,所以如果要使用多点委托,应该用void,否则你的编译会返回一个错误
● 多点委托不建议你的参数列表中有OUT的类型,这样只会out最后一个方法的值,其他的值会丢失。
3.委托的理解
首先申明,这只是我举的一个例子,目的是帮助理解委托的过程,其中很多地方都经不起推敲,望大家知悉。言归正传,
你想要吃饭,
但是自己又不会做(委托方不知道实现细节),
你计划找个饭店,叫个回锅肉饭(定义了一个委托)
你决定找常去的那家叫做A的饭店(实例化一个委托)
你打电话给A饭店(委托调用)
A饭店给你做好了你的回锅肉饭(代理函数工作)
饭来了,真好。
4.委托的使用时机
当你需要把一个方法传送给其他方法时,可以考虑使用委托。好像不是很好理解,也可以这样说,当你确定要处理一件事,但又不能确定处理方法时,可以考虑用委托。其实单独的说委托的应用好像有点牵强,委托更多的是在事件中的应用。
5.一个委托的例子
我用两个类来做这个例子,一个类,我称它为委托方,一个类我称它为代理方,代码如下:
using System;
namespace Visen.Demo.Delegate
{
///<summary>
/// StartUp 委托演示中的程序入口,含委托方。
///</summary>
class StartUp
{
#region公用的方法
#region应用程序的主入口点。
///<summary>
///应用程序的主入口点。
///</summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("This is a delegate demo\n");
Visen.Demo.Delegate.Agent ag = new Agent();
//定义一个委托类型的对象
OutMessage singleDele = new OutMessage(ag.ShowMessage);
OutMessage deleStaticMeth = new OutMessage(Agent.SShowMessage);
//定义一个多点委托
OutMessage MultiDele = new OutMessage(ag.ShowMessage);
MultiDele += new OutMessage(Agent.SShowMessage);
singleDele(" delegate instance singleDele");
deleStaticMeth(" delegate instance deleStaticMeth");
MultiDele(" this is a MultiDele");
Console.Read();
}
#endregion应用程序的主入口点。
#endregion公用的方法
#region私用的字段
///<summary>
///定义一个委托类型
///</summary>
private delegate void OutMessage(string msg);
#endregion私有的字段
}
}
下面是代理方:
using System;
namespace Visen.Demo.Delegate
{
///<summary>
/// Agent 类为委托者的代理方,处理委托者委托的事务。
///</summary>
public class Agent
{
#region公用的方法
#region空的构造函数
///<summary>
///空的构造函数
///</summary>
public Agent()
{
}
#endregion空的构造函数
#region显示一条信息到控制台,一个类成员函数作为代理方
///<summary>
///显示一条信息到控制台,一个类成员函数作为代理方
///</summary>
///<param name="msg">显示内容</param>
public void ShowMessage(string msg)
{
Console.WriteLine("Method ShowMessage out:" + msg + "\n");
}
#endregion显示一条信息到控制台,一个类成员函数作为代理方
#region显示一条信息到控制台,一个类静态函数作为代理方
///<summary>
///显示一条信息到控制台,一个类静态函数作为代理方
///</summary>
///<param name="msg">显示信息</param>
public static void SShowMessage(string msg)
{
Console.WriteLine("static Method SShowMessage out:" + msg + "\n");
}
#endregion显示一条信息到控制台,一个类静态函数作为代理方
#endregion公用的方法
}
}
输出为:
This is a delegate demo
Method ShowMessage out: delegate instance singleDele
static Method SShowMessage out: delegate instance deleStaticMeth
Method ShowMessage out: this is a MultiDele
static Method SShowMessage out: this is a MultiDele
可见:方法函数可以是类成员函数,也可以是一个静态成员,只要和委托的签名相同就可以了。
有错的地方,请大家批评指正,谢谢!
J. 谁帮我写个C# delegate回调函数的例子,谢谢了
首先创建一个很简单的委托~
public delegate void DoIt(string str);
然后创建一个委托引用~
public DoIt _DoIt;
之后就是在你程序需专要触发回调函数的属地方去执行这个委托~
if (_DoIt != null) //执行委托需要判断是否为空,如果没有将对应签名的方法存入委托,直接执行会报错
{
_DoIt("测试");
}
最后就是去为委托添加回调方法,签名必须一样~
_DoIt = (str) => //这里是一个匿名函数,当然也可以直接传方法
{
//这里就是委托触发时执行的代码
};
唔~看不懂请追问~
希望对您有帮助~
By Billskate