我有两个类库。一个是普通的.NET程序集,另一个是Compact Framework设备程序集链接桌面类文件。该库负责服务器和客户端之间的TCP异步操作。
现在我为服务器和Windows Mobile Forms设备项目创建一个Windows项目作为客户端。
我在客户端和服务器的Data Received上使用了一些事件。要通过TCP安全接收来自ASync接收数据的数据,我使用Control类dummy来检查是否需要Invoke。
奇怪的是,当从服务器向设备CF客户端发送数据时,数据不需要对需要显示数据的控件进行任何线程处理。 但是从客户端向服务器发送数据我得到了跨线程操作异常。
这是一些代码。
我用来保护数据的静态方法。
public static void InvokeIfNecessary(Control control, Action setValue)
{
if (control.InvokeRequired)
{
control.Invoke(setValue);
}
else
{
setValue();
}
}
当我想抛出来自TCP通信的数据时。
if (OnClientChangeConnection != null) SafeData.InvokeIfNecessary(_helpControl, () => OnClientChangeConnection(ConnectedClients, requestClientInfo));
我知道为什么会出现这种行为?或者更好地处理这个问题?
谢谢!
答案 0 :(得分:1)
由于您要定义InvokeIfNecessary
,请注意“必要时”部分。这意味着请求可能与调度程序位于不同的线程上。请注意我说“可能” - 这意味着它可能不会,也可能来自调度员。
完整框架和紧凑框架可以使用不同的线程来处理异步操作。例如,紧凑框架可以是单线程的(因为它在Mobile上运行),而服务器完整框架可以是多线程的。 API看起来相同,但数据可能来自不同的线程。
一个很好的例子是Silverlight,它使用调度程序线程(即主UI线程)来进行网络访问和填充,即使您使用的是BeginXXX / EndXXX异步调用。因此,如果您在此移动环境中运行简单的代码,您将不会获得线程异常,但您肯定可能在服务器上获得一个,其中BeginXXX / EndXXX调用可能会转到不同的线程 - - 他们可能不会,这实际上取决于服务器在通话时的决定。
因此,您始终需要确定请求是否可能来自其他线程。使用类似InvokeIfNecessary
之类的东西是必要的邪恶并且是正确的做法 - 不要因为在某些环境中你没有看到问题而忽略它。