0

When ever I press the send button the TCP Client, it stops the TCP Server and throws me this error.

The calling thread cannot access this object because a different thread owns it.

I've tried debugging it but couldnt find the issue. How would I be able to fix this since it is bugging me alot and I am new to TCP / IP and threading aswell. I know how it works but yeah.

In the listenerThread() method its this line that is throwing me this error.

lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");

using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Text;


namespace SimpleTCPServer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ArrayList nSockets;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
            lblStatus.Content = "My IP address is " + IPHost.AddressList[0].ToString();
            nSockets = new ArrayList();
            Thread thdListener = new Thread(new ThreadStart(listenerThread));
            thdListener.Start();
        }


        public void listenerThread()
        {
            TcpListener tcpListener = new TcpListener(8080);
            tcpListener.Start();
            while (true)
            {
                Socket handlerSocket = tcpListener.AcceptSocket();
                if (handlerSocket.Connected)
                {
                    Control.CheckForIllegalCrossThreadCalls = false;
                    lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
                    lock (this)
                    {
                        nSockets.Add(handlerSocket);
                    }
                    ThreadStart thdstHandler = new
                    ThreadStart(handlerThread);
                    Thread thdHandler = new Thread(thdstHandler);
                    thdHandler.Start();
                }
            }
        }

        public void handlerThread()
        {
            Socket handlerSocket = (Socket)nSockets[nSockets.Count - 1];
            NetworkStream networkStream = new NetworkStream(handlerSocket);
            int thisRead = 0;
            int blockSize = 1024;
            Byte[] dataByte = new Byte[blockSize];
            lock (this)
            {
                // Only one process can access
                // the same file at any given time
                Stream fileStream = File.OpenWrite("c:\\my documents\\SubmittedFile.txt");
                while (true)
                {
                    thisRead = networkStream.Read(dataByte, 0, blockSize);
                    fileStream.Write(dataByte, 0, thisRead);
                    if (thisRead == 0) break;
                }
                fileStream.Close();
            }
            lbConnections.Items.Add("File Written");
            handlerSocket = null;
        }

    }
}

TCP Client

using Microsoft.Win32;
using System.IO;
using System.Net.Sockets;
using System.Windows;
using System.Threading;
using System.Net;
using System.Text;
namespace SimpleTCPClient

{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void browseButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == true)
                fileTextbox.Text = (openFileDialog.FileName);

        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            Stream fileStream = File.OpenRead(fileTextbox.Text);
            // Alocate memory space for the file
            byte[] fileBuffer = new byte[fileStream.Length];
            fileStream.Read(fileBuffer, 0, (int)fileStream.Length);
            // Open a TCP/IP Connection and send the data
            TcpClient clientSocket = new TcpClient(ipTextbox.Text, 8080);
            NetworkStream networkStream = clientSocket.GetStream();
            networkStream.Write(fileBuffer, 0, fileBuffer.GetLength(0));
            networkStream.Close();
        }
    }
}

1 Answers1

1

if lbConnections is a client control, you cannot modify it from a background thread - you must invoke a method that will do the updating on the GUI thread. There's effectively no thread safety around GUI controls, and all disabling Control.CheckForIllegalCrossThreadCalls does is make it less obvious when you shoot yourself in the foot.

In general, you have other problems. For example, your handler thread always tries to grab the last connection - there's a very real possibility that two connections could happen (and both be added to nSockets) before either of the handler threads try to grab the sockets - meaning one socket never gets grabbed and one gets grabbed twice. Plus, it looks like you never actually dispose any of the socket objects, or even allow them to be GCd, since I don't see any code that removes from nSockets.

You really have two good options - either pass the handler thread the data it needs, or use something like a queue and have the handler thread dequeue one socket and operate on it (of course all queue access must be synchronized). Either way you should be disposing of the sockets and not keeping them around forever.

PMV
  • 2,058
  • 1
  • 10
  • 15