简体   繁体   English

使用BackgroundWorker WPF并出现错误:无法访问已处置的对象

[英]Using BackgroundWorker WPF and getting error: Cannot access a disposed object

I am fairly new to multi threading, therefore please excuse any obvious mistakes which may be present - I am still learning! 我对多线程还很陌生,因此请原谅可能出现的任何明显错误-我仍在学习!

I currently have a program which reads in from a port using TCPClient and NetworkStream and outputs the data to a text box in a WPF program. 我目前有一个程序,该程序使用TCPClientNetworkStream从端口读取数据,并将数据输出到WPF程序中的text box Nonetheless, when trying to read in multiple times from the stream , it slows the program down quite noticeably and the more it has to read, the longer it takes for the program to open. 但是,当尝试从stream中多次读取时,它会明显降低程序运行速度,并且读取的次数越多,打开程序所花费的时间就越长。 Therefore I decided to try and implement threading and I am trying to use Background Worker . 因此,我决定尝试实现threading并且尝试使用Background Worker

Here is the code I have in the MainWindow : 这是我在MainWindow拥有的代码:

InitializeComponent();

    try
    {
        client.Connect(address, port); //connect to the client 
        nwStream = client.GetStream(); //read in data from stream
        readInTxtBox.Text = ("Connection Open");
        BackgroundWorker worker = new BackgroundWorker(); 

        worker.DoWork += worker_DoWork; 
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync();

    }
    catch (SocketException ex)
    {
        readInTxtBox.Text = ex.ToString(); //write out the error
    }
    finally
    {
        client.Close();
    }

This is the worker_DoWork and worker_RunWorkerCompleted methods: 这是worker_DoWorkworker_RunWorkerCompleted方法:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    if (Dispatcher.CheckAccess())
    {
        ReadIn();
    }
    else
    {
        Dispatcher.BeginInvoke(new Action(() =>
        {
            ReadIn();
        }));
    }
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Dispatcher.BeginInvoke(new Action(() =>
    {
        OutputToTextBoxInput();

    }));

}

When stepping through, it does go to the Dispatcher.BeginInvoke action on the worker_DoWork , and fails on the first line of the ReadIn() method : 单步执行时,它确实转到worker_DoWork上的Dispatcher.BeginInvoke操作,并在ReadIn()方法的第一行失败:

private void ReadIn()
{
    byte[] b = Utilities.ReadInBytes(client, nwStream); //fails here!
    hex = Utilities.ConvertByteToHex(b);
    nwStream.Close();
}

It fails on the following line of the ReadInBytes method, with the error: Cannot access a disposed object. 它在ReadInBytes方法的以下行中fails ,并显示错误: Cannot access a disposed object.

public static byte[] ReadInBytes(TcpClient client, NetworkStream nwStream)
{
    byte[] bytesToRead = new byte[client.ReceiveBufferSize]; //FAILS HERE
    int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
    ArraySegment<byte> segment = new ArraySegment<byte>(bytesToRead, 0, bytesRead);

    return segment.ToArray();
} 

The client and network stream are declared as public statics . clientnetwork stream被声明为public statics I have had this problem when using invoke and when not. 使用invoke和不使用invoke时,我都遇到了这个问题。 I have also tried BeginInvoke and the same problem has occurred. 我也尝试了BeginInvoke并且发生了相同的问题。 Any help would be massively appreciated as well as any explanations on where I have gone wrong! 我们将不胜感激任何帮助以及对我哪里出错了的任何解释!

The problem is, that you dispose the client in the finally block, but use it in the DoWork methods which is running later. 问题是,您将客户端放置在finally块中,但是在稍后运行的DoWork方法中使用它。

To solve it, create, connect and clode the client in the DoWork event :). 要解决此问题,请在DoWork事件中创建,连接和克隆客户端:)。


As mentioned in a comment, you should not dispatch your code in the DoWork method! 如评论中所述,您不应在DoWork方法中分派代码! Just call ReadIn there. 只需致电ReadIn。 You want to run the code in background, so that the GUI remains resposable - it makes no sense to push it to the GUI thread! 您想在后台运行代码,以使GUI保持可回收状态-将其推送到GUI线程毫无意义!

It is also not required to dispatch the code in the RunWorkerCompleted event handler, because the background work does it for you ;). 也不需要在RunWorkerCompleted事件处理程序中分派代码,因为后台工作会为您完成代码;)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM