来自另一个线程的异步TCP数据不安全。跨线程操作

时间:2011-05-15 18:43:49

标签: .net asynchronous c#-3.0 tcp multithreading

我有两个类库。一个是普通的.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));

我知道为什么会出现这种行为?或者更好地处理这个问题?

谢谢!

1 个答案:

答案 0 :(得分:1)

由于您要定义InvokeIfNecessary,请注意“必要时”部分。这意味着请求可能与调度程序位于不同的线程上。请注意我说“可能” - 这意味着它可能不会,也可能来自调度员。

完整框架和紧凑框架可以使用不同的线程来处理异步操作。例如,紧凑框架可以是单线程的(因为它在Mobile上运行),而服务器完整框架可以是多线程的。 API看起来相同,但数据可能来自不同的线程。

一个很好的例子是Silverlight,它使用调度程序线程(即主UI线程)来进行网络访问和填充,即使您使用的是BeginXXX / EndXXX异步调用。因此,如果您在此移动环境中运行简单的代码,您将不会获得线程异常,但您肯定可能在服务器上获得一个,其中BeginXXX / EndXXX调用可能会转到不同的线程 - - 他们可能不会,这实际上取决于服务器在通话时的决定。

因此,您始终需要确定请求是否可能来自其他线程。使用类似InvokeIfNecessary之类的东西是必要的邪恶并且是正确的做法 - 不要因为在某些环境中你没有看到问题而忽略它。