c#System.InvalidOperationException

Bri*_*rin 7 c# client asynchronous tcp

一般

我正在尝试在C#中编写一个非常简单的TCPIP客户端服务器来连接到具有端口号的IP地址,并询问非常简单的行命令,然后将回复放在网格箱,图形或其他显示选项中.

我已经在网上找到了一个可以下载的实用程序,由Jayan Nair编写,这似乎正确地发送消息,并收到回复确定.

当我尝试将回复数据加载到richtext或GridView时出现问题.

我得到的错误消息是: - System.InvalidOperationException

我问过微软论坛,他们给了我一个非常复杂,含糊不清和过度参与的关于我应该做什么的指示,这涉及一些名为INVOKE和BeginInvoke的东西,而且他们整个事情似乎都是一个项目;它自己对.

我所追求的只是一个有效的例子,而不是太复杂.

这是代码: -

        try
        {
            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
            int iRx = theSockId.thisSocket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            // 
            System.String szData = new System.String(chars);
            richTextRxMessage.Text =  szData;  // fails
            //textBox1.Text = szData;          // also fails
            WaitForData();
        }
Run Code Online (Sandbox Code Playgroud)

这是错误信息: -

base {System.Windows.Forms.TextBoxBase} = {Text = '((System.Windows.Forms.RichTextBox)    (((System.Windows.Forms.RichTextBox)(richTextRxMessage)))).Text' threw an exception of type   'System.InvalidOperationException'}
Run Code Online (Sandbox Code Playgroud)

附加信息是: - szData包含大约6300个字符,包括制表符(9)和返回(13),并且与服务器发送的消息一致我也尝试使用文本框而不是richtext,结果相同

对于那些感兴趣

这是Microsoft链接

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/12a67fb0-847e-4e2b-baa8-ef6ceed60aa4/


  • 这里只是我尝试过的两个代码修改,两个都在相同的错误条件下失败
  • 我认为我需要做的是以更低的水平开始C#而不仅仅是跳进去并希望最好


       public void OnDataReceived(IAsyncResult asyn)
        {
    
            int InputRx;
            int charLen;
            char[] Inputchars;
            System.Text.Decoder InputDecode;
            System.String szData;
            bool IfInvokeRequired;
    
            try
    
            {
    
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                InputRx = theSockId.thisSocket.EndReceive(asyn);                    // get size of input array
                Inputchars = new char[InputRx + 1];                                   // put i char array
                InputDecode = System.Text.Encoding.UTF8.GetDecoder();
                charLen = InputDecode.GetChars(theSockId.dataBuffer, 0, InputRx, Inputchars, 0);
                szData = new System.String(Inputchars);
                IfInvokeRequired = richTextRxMessage.InvokeRequired;
                if (IfInvokeRequired == true)
                {
                    richTextRxMessage.Invoke((MethodInvoker)delegate { this.Text = szData; });// fails
                    richTextRxMessage.BeginInvoke(new MethodInvoker(() => richTextRxMessage.Text = szData));//fails as well
                }
    
    Run Code Online (Sandbox Code Playgroud)
  • Use*_*678 5

    InvalidOperationException您收到可能有内部异常" 因为不同的线程拥有它调用线程不能访问该对象 ".

    为了调试,您可以快速设置CheckForIllegalCrossThreadCalls为false.这将阻止运行时抛出异常,但仅仅因为您没有收到异常并不意味着它们没有发生,所以这对于分布式软件来说是一种不好的做法,但是非常方便调试.

    为了解决您的问题,您需要调用一个与交互的代码RichTextBoxUI线程又名控制上创建线程,并且允许运行与控制交互代码的唯一线索.

    要调用UI线程上的代码,您可以使用以下简洁的语句:

    richTextRxMessage.BeginInvoke(new MethodInvoker(() => richTextRxMessage.Text = szData));
    
    Run Code Online (Sandbox Code Playgroud)

    很简单,您在这里所做的就是通过委托传递您希望在UI线程上调用的语句.


    Nev*_*vyn 0

    微软的答案并不完全错误,但还有其他更简单的方法,尽管它们看起来并不那么简单。

    这是我自己的代码的片段,可能对您有用。

    if (dirtyImage.InvokeRequired)
    {
        dirtyImage.Invoke(new MethodInvoker(delegate { Visible = RigX.IsDirty; }));
        dirtyImage.Invoke(new MethodInvoker(delegate { Refresh(); }));
    }
    else
    {
        dirtyImage.Visible = RigX.IsDirty;
        dirtyImage.Refresh();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请注意如何使用InvokeRequireddirtyImage.Invoke(...)使用。我通过创建委托并使用方法调用器使其变得更加简单,这样我就可以将所有调用都放在一个衬垫中。该委托本质上创建了一个迷你方法,然后使用 MethodInvoker 调用该方法。因为更改是在 UI 线程上进行的,所以如果不使用 则无法从后台线程调用它们.Invoke,这是不允许的。

    您的呼叫可以通过这种方式更改:

    richTextRxMessage.Invoke(new MethodInvoker(delegate { Text =  szData; }));
    
    Run Code Online (Sandbox Code Playgroud)

    该调用也可以直接从 UI 线程本身进行,因此您实际上不需要 if 语句,但它是“成本”,它比直接调用属性慢。

    当然,只有当您一开始就在后台线程上时,这才会真正产生影响。如果不是,那么您需要调查错误本身。也许返回的文本有问题,将其写入文件并查看,看看是否可以发现问题。尝试手动设置 RTB 文本,看看它是否允许这种情况发生。等等等等等等。