Using BackgroundWorker WPF and getting error: Cannot access a disposed object
Using BackgroundWorker WPF and getting error: Cannot access a disposed object
我对多线程还很陌生,因此请原谅可能存在的任何明显错误 - 我还在学习!
我目前有一个程序使用 TCPClient
和 NetworkStream
从端口读取数据并将数据输出到 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_DoWork
和 worker_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();
}
它 fails
在 ReadInBytes
方法的下一行,错误: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();
}
client
和 network stream
声明为 public statics
。我在使用 invoke
和不使用时遇到过这个问题。我也试过 BeginInvoke
也出现了同样的问题。
任何帮助以及对我哪里出错的任何解释都将不胜感激!
问题是,您在 finally 块中处理客户端,但在 运行ning 之后的 DoWork
方法中使用它。
要解决它,请在 DoWork 事件中创建、连接和关闭客户端:)。
如评论中所述,您不应在 DoWork 方法中分派代码!只需在那里调用 ReadIn。您想要 运行 后台代码,以便 GUI 保持可响应 - 将它推送到 GUI 线程是没有意义的!
也不需要分派 RunWorkerCompleted 事件处理程序中的代码,因为后台工作会为您完成 ;)。
我对多线程还很陌生,因此请原谅可能存在的任何明显错误 - 我还在学习!
我目前有一个程序使用 TCPClient
和 NetworkStream
从端口读取数据并将数据输出到 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_DoWork
和 worker_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();
}
它 fails
在 ReadInBytes
方法的下一行,错误: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();
}
client
和 network stream
声明为 public statics
。我在使用 invoke
和不使用时遇到过这个问题。我也试过 BeginInvoke
也出现了同样的问题。
任何帮助以及对我哪里出错的任何解释都将不胜感激!
问题是,您在 finally 块中处理客户端,但在 运行ning 之后的 DoWork
方法中使用它。
要解决它,请在 DoWork 事件中创建、连接和关闭客户端:)。
如评论中所述,您不应在 DoWork 方法中分派代码!只需在那里调用 ReadIn。您想要 运行 后台代码,以便 GUI 保持可响应 - 将它推送到 GUI 线程是没有意义的!
也不需要分派 RunWorkerCompleted 事件处理程序中的代码,因为后台工作会为您完成 ;)。