【问题标题】:Using BackgroundWorker WPF and getting error: Cannot access a disposed object使用 BackgroundWorker WPF 并出现错误:无法访问已处置的对象
【发布时间】:2017-07-31 10:49:04
【问题描述】:

我对多线程相当陌生,因此请原谅可能存在的任何明显错误 - 我还在学习!

我目前有一个程序,它使用TCPClientNetworkStream 从端口读取数据并将数据输出到 WPF 程序中的text box。尽管如此,当尝试从stream 多次读取时,它会显着降低程序速度,并且读取的次数越多,程序打开所需的时间就越长。因此我决定尝试实现threading,我正在尝试使用Background Worker

这是我在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();
    }

这是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();

    }));

}

当单步执行时,它会转到worker_DoWork 上的Dispatcher.BeginInvoke 操作,并在ReadIn() 方法的第一行失败:

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

failsReadInBytes方法的下面一行,错误: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();
} 

clientnetwork stream 被声明为 public statics。我在使用invoke 时遇到了这个问题,而在没有的时候。我也试过BeginInvoke,也出现了同样的问题。 任何帮助以及对我哪里出错的任何解释都将不胜感激!

【问题讨论】:

  • 为什么要发送ReadIn?如果你想在 GUI 线程上运行它,使用 BackgroundWorker... 是没有意义的 ;)
  • 在 GUI 线程上运行时似乎真的很慢
  • 其实我希望上面的代码更慢:P
  • 啊,好吧,您认为哪种方法最合适?这个想法是我想循环 ReadIn() 方法以从流中多次读取,因为来自端口的数据是连续的。这就是为什么我觉得有一个与 GUI 不同的线程会更合适,这样它就不会减慢其他进程。
  • 因为人们通常会启动很多它们,并且由于这种方法涉及为每个工作人员打开一个新线程,这会导致系统性能问题。人们只是不明白他们在做什么。他们使用的 API 越低,对他们编写的应用程序造成的伤害就越大。

标签: c# wpf multithreading backgroundworker


【解决方案1】:

问题是,您在 finally 块中处理客户端,但在稍后运行的 DoWork 方法中使用它。

要解决它,请在 DoWork 事件中创建、连接和关闭客户端 :)。


正如评论中提到的,您不应该在 DoWork 方法中调度您的代码!只需在那里调用ReadIn。您想在后台运行代码,以便 GUI 保持可使用状态 - 将其推送到 GUI 线程是没有意义的!

也不需要在 RunWorkerCompleted 事件处理程序中分派代码,因为后台工作会为您完成;)。

【讨论】:

  • 非常感谢!很生气自己没有尝试哈哈 :)
  • 请注意,任何对 GUI 控件的访问(例如 readInTxtBox.Text = ("Connection Open");)都必须在方法 DoWork 中调度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 2011-10-23
  • 2011-03-25
相关资源
最近更新 更多