来自不同线程的访问对象
我有一个服务器类,它基本上等待来自客户端的连接。在该类中,我创建了一个NetworkStream对象,以便能够从客户端接收字节。因为NetworkStream.Read()方法不是异步的(意味着它将等待,直到它从客户端读取字节以继续执行类似于messagebox方法的代码),那么我必须读取单独线程中的字节,以便如果程序碰巧等待读取数据,则使用程序的用户仍然可以与程序交互。来自不同线程的访问对象
反正很多对象都属于该线程。一个例子是我有一个名为日志的List。我使用该列表来了解服务器的状态。也许它正在监听连接,或者它的状态是“连接”或“断开”。
所以,如果我这样做:
Server myServer = new Server("192.168.0.120","1300"...\\ I pass the appropite parameters in order to instantiate it
//...
.. then I am able to latter look at the log as
string foo = myServer.Log[0] for example.
,因为我想知道当日志被更新,服务器类我已经创建了一个事件为:
public delegate void onUpdateHandler(string newStatus);
public event onUpdateHandler onUpdate = delegate { };
然后我火事件在服务器类为:
onUpdate("waitingForConnection");
和我收到这些事件与方法:
但如果我尝试做一些NEWSTATUS我得到的错误,指出:
System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
所以我怎么能传递一个对象与事件?
编辑
,所以我也注意到,如果我这样做:
我也得到一个错误!
但是当我做呼叫从一个按钮,同样的事情:
// SERVER IS RUNNING BEFORE CALLING THIS METHOD
private void button3_Click(object sender, RoutedEventArgs e)
{
listView1.Items.Add("my own string");
}
我没有得到一个错误!
为什么我在事件中遇到错误,并且在用常规按钮调用时没有遇到错误。
的问题是,该线程试图访问ListView控件这是一个DependencyObject
具有线程关联,使用Dispatcher
到UI线程上执行这样的方法,如:
Application.Current.Dispatcher.Invoke((Action)(() =>
{
listView1.Items.Add(newStatus);
}));
另请参见threading model reference获取更多信息。
问题不在于您尝试使用您发送给该方法的值进行操作,而是您尝试使用该方法的问题。
事件处理程序仍在后台线程中运行,并且从那里您不能使用任何UI控件,因为它们属于主线程。
处理的常用方法是使用CheckAccess
方法来检查,如果你需要切换踏板,以及Invoke
方法来交班工作,主线程:当我把里面
void server_onUpdate(string newStatus) {
if (!listView1.Dispatcher.CheckAccess()) {
listView1.Dispatcher.Invoke(server_onUpdate, newStatus)
} else {
listView1.Items.Add(newStatus);
}
}
我的方法我得到一个错误,指出:不能转换lambda表达式键入'System.Delegate',因为它不是一个委托类型 –
@TonoNam:哦,是的,你需要投它,或明确创建一个行动。 –
@Tono,lambda必须被铸造成某种代表类型,请参阅我的编辑。 – svick