【发布时间】:2012-02-08 10:04:59
【问题描述】:
我正在尝试触发一个方法作为对 NetworkStream 的异步读取操作的结果。读取操作通过 BeginRead 和 EndRead 完成,导致在 BeginRead 指定的回调中调用 EndRead。所有非常基本的东西。现在,由于回调是在系统生成的线程中完成的,从 NetworkStream 读取的数据不再属于我的线程,即 BeginRead。为了克服这个问题,我编写了一个方法来进一步处理读取的数据,我尝试通过我的 Thread 的调度程序调用它。
// These are created in my Thread
private delegate void ReceiverCallback(IPEndPoint sender, byte[] data);
private Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
回调看起来像这样:
private void DataReceived(IAsyncResult result)
{
DataReceivedStruct drs = (DataReceivedStruct)result.AsyncState;
NetworkStream used = drs.stream;
AutoResetEvent handle = drs.waitHandle;
used.EndRead(result);
DispatchRaiseReceived(readBuffer);
handle.Set();
}
DataReceivedStruct 是一个包含 NetworkStream 和 AutoResetEvent 的简单结构。 ReadBuffer 是一个长度为 1024 的全局私有 byte[],因为 BeginRead 和 EndRead 不是在同一个方法中调用的。
DispatchRaiseReceive 方法如下所示:
private void DispatchRaiseReceived(byte[] data)
{
dispatcher.BeginInvoke((ReceiverCallback)RaiseReceived, socket.Client.RemoteEndPoint, data);
}
其中 socket 是一个 TcpClient 对象。
分派的方法类似于以下代码。这样做只是通过事件传递数据以进行进一步处理。
private void RaiseReceived(IPEndPoint sender, byte[] data)
{
if(IsEnabled){
if (Received != null)
{
Received(this, new TCPDataArgs(sender, data));
}
}
}
调度程序需要调用的实际方法永远不会被调用。现在从我在网上可以找到的是,它可能与未在正确的线程上创建调度程序有关,因此它永远不会在正确的线程上调用方法。但是,调度程序是在我的线程上创建的,因此不应该适用。
【问题讨论】:
-
尝试使用 Invoke 而不是 BeginInvoke。报告发生了什么。
-
同样的效果,它不会被调用。
-
您确定您的原始线程,即实例化您的类和
private Dispatcher dispatcher = Dispatcher.CurrentDispatcher;的线程此时仍然处于活动状态? -
可能由于某种原因调度程序正在关闭。检查HasShutdownStarted 和HasShutdownFinished 标志。
-
@Avner,是的,因为那是我的 UI-Tread。而且由于程序还在运行,所以我知道 Thread 仍然存在。
标签: c# wpf delegates dispatcher