围绕这个进行了很多讨论,每个人都倾向于同意你应该总是调用Delegate.EndInvoke来防止内存泄漏(甚至Jon Skeet说过它!).
我总是毫不疑问地遵循这个准则,但最近我实现了自己的AsyncResult类,并发现可能泄漏的唯一资源是AsyncWaitHandle.
(事实上它并没有真正泄漏,因为WaitHandle使用的本机资源被封装在一个具有Finalizer的SafeHandle中,但它会对垃圾收集器的finalize队列施加压力.即便如此,AsyncResult的良好实现也会只按需初始化AsyncWaitHandle ...)
了解是否存在泄漏的最佳方法就是尝试:
Action a = delegate { };
while (true)
a.BeginInvoke(null, null);
Run Code Online (Sandbox Code Playgroud)
我运行了一段时间,内存保持在9-20 MB之间.
让我们与调用Delegate.EndInvoke时进行比较:
Action a = delegate { };
while (true)
a.BeginInvoke(ar => a.EndInvoke(ar), null);
Run Code Online (Sandbox Code Playgroud)
通过这个测试,内存在9-30 MG之间播放,怪异的呃?(可能是因为当存在AsyncCallback时执行需要更长的时间,因此ThreadPool中将有更多的排队委托)
你觉得怎么样......"神话被破坏了"?
PS ThreadPool.QueueUserWorkItem比Delegate.BeginInvoke效率高一百,它更适合用于fire&forget调用.
用异步委托(回调)替换线程(而不是ThreadPool线程).
我的场景:为每个客户端生成一个Thread/del.beginInvoke().
据我说,
原因
如果上述原因错误,请纠正我.
例
public delegate void SendCallbackType();
SendCallbackType senderdel= new SendCallbackType(SendData);
public void StartSend() // This method Could be Called more than 700 times (Thread per Client)
{
senderdel.BeginInvoke(SendCallback,null);
// (or)
Thread t = new Thread(new ThreadStart(ThreadSend));
t.IsBackground = true;
t.Start();
}
//Async Delegate
void SendData()
{
string data = QueData.DeQueue();
RaiseOnData(data); // Raise to event.
}
void SendCallback(IAsyncResult ar)
{
senderdel.BeginInvoke(SendCallback, null);
}
//Thread
void ThreadSend()
{
while (true) …Run Code Online (Sandbox Code Playgroud)