为什么我的对象被另一个线程使用

本文关键字:线程 另一个 我的 对象 为什么 | 更新日期: 2023-09-27 18:14:38

每当我按下TCP客户端的发送按钮时,它会停止TCP服务器并抛出此错误。

调用线程不能访问这个对象,因为一个不同的线程拥有它。

我试着调试它,但找不到问题。我怎么能解决这个问题,因为它是困扰我很多,我是新的TCP/IP和线程。我知道它是怎么工作的,但是是的。

在listenerThread()方法中,正是这一行抛出了这个错误。

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客户机

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();
        }
    }
}

为什么我的对象被另一个线程使用

如果lbConnections是一个客户端控件,您不能从后台线程修改它——您必须调用一个方法来在GUI线程上进行更新。GUI控件周围实际上没有线程安全,并且所有控件都禁用。当你搬起石头砸自己的脚时,CheckForIllegalCrossThreadCalls的作用是使它不那么明显。

一般来说,你还有其他问题。例如,你的处理程序线程总是试图抓取最后一个连接——在任何一个处理程序线程试图抓取套接字之前,很有可能发生两个连接(并且都被添加到nSockets中)——这意味着一个套接字永远不会被抓取,一个套接字被抓取两次。另外,看起来你从来没有真正处理过任何套接字对象,或者甚至允许它们成为GCd,因为我没有看到任何代码从nSockets中删除。

你真的有两个很好的选择——要么传递给处理程序线程它需要的数据,或者使用类似队列的东西,让处理程序线程去队列一个套接字并对它进行操作(当然所有队列访问必须同步)。无论哪种方式,您都应该处理套接字,而不是永远保留它们。