为什么异步回调套接字方法通常是静态的?

时间:2010-09-09 15:55:41

标签: c# c++ sockets asynchronous static

为什么异步回调套接字方法通常是静态的? (假设我理解静态类,方法和数据对象)。如果使用这些作为实例方法编写类,是否会出现基本的设计/逻辑错误?有什么特别的,应该小心避免吗?

3 个答案:

答案 0 :(得分:3)

没有特别的理由说它们应该是静态的。这一切都取决于你的设计。

如果回调需要访问类中的成员,则可以将其声明为实例成员。但是,您需要确保正确同步对实例成员的访问,因为可以从不同的线程同时调用回调。

我猜你看到的所有例子都通过IAsyncResult.AsyncState将所需数据传递给回调,因此不需要来自该类的其他信息。如果你能做到这一点,它可以简化你的代码,因为你不再需要担心线程同步等。

<强>更新

只是澄清一下,根据评论,似乎我应该更加明确。并不是静态回调是线程安全的,而是在设计中将所需数据传递给回调,当然这些数据不被其他线程共享,因此不需要锁定。并且由于回调传递了它所需的所有数据,因此它不需要访问类实例,因此可以变为静态。

答案 1 :(得分:1)

回调函数通常是静态的,因为您不知道要回拨的类的任何内容。

实际上,类实例函数通常将“this”指针作为隐藏的第一个参数。

请参阅:http://www.drdobbs.com/184403375;jsessionid=P5JGJLQBDYGWBQE1GHOSKH4ATMY32JVN?pgno=2

修改:另请参阅Why callback functions needs to be static when declared in class

答案 2 :(得分:1)

至少在C ++中,非静态方法希望接收this作为隐藏参数。因为无论什么调用它作为回调都不知道,它不会传递那个额外的参数。如果您确实设法将非静态成员函数作为回调调用,那么任何试图使用成员数据的事件(通过this发生)都会(几乎可以肯定)存在重大问题。

我猜C#至少有点类似,但我还没有详细研究细节以确定。无论语言如何,代码都需要知道要使用哪些数据。明显的区别是C#还支持委托,这对回调非常有用。

编辑:关于如何避免这种情况,至少在C ++中它很简单。您通常希望使用ACEBoost ASIOPOCO这样的库来保护您免受大多数混乱细节的影响。如果你做一些环顾四周,你可能会发现至少几十个其他人。哦,我应该补充一点,大多数应用程序框架样式的库(例如,wxWidgetsQt)都包含类,以保护您免受大多数混乱细节的影响。明显的区别在于,这些通常会“接管”应用程序的设计(但是,公平地说,我应该补充一点,ACE倾向于相同)。

当然,人们也为C#编写了库,但是我还没有使用足够的文档来对它们做出有意义的推荐。这里很多还取决于你正在寻找的抽象级别。 WCF(例如)做的不仅仅是保护你免受凌乱的细节。相反,它基本上构建了自己完整的如何使用网络的想法,恰好(在那里的某个地方)能够使用套接字 - 但在大多数情况下,并没有真正起作用随着套接字,你正在使用WCF,它碰巧使用套接字。

然而,最终,图书馆只是隐藏,而不是改变,真正发生的事情。在库中的某个地方,Winsock回调静态成员函数或使用它期望的基本C调用约定的自由函数。然后该函数使用额外的数据(通常是传递给它的参数)来确定从那里调用的内容。你的代码与Winsock的回调之间有一层“绝缘”的厚度有多大。