我正在处理与服务器通信的应用程序。
thread = new Thread(new ThreadStart(ClientStart));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
private void ClientStart()
{
tcpClient = new TcpClient(ip,3000);
stream = tcpClient.GetStream();
while (true) {
stream.Read(...);
PrintMessage(...);
.....
}
}
private void PrintMessage(LogWin w, string msg)
{
DateTime dt = DateTime.Now;
w.GetMessageBox().Dispatcher.BeginInvoke(DispatcherPriority.Input,new Action(()=>w.GetMessageBox()
.AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));
}
稍后我需要将结果打印到消息框。我知道我必须使用Dispatcher,因为我在另一个线程中工作,但即使我使用beginInvoke方法,我的应用程序也会冻结。
根据Sheridan的回答进行编辑:
现在我得到: WindowsBase.dll
中出现未处理的“System.InvalidOperationException”类型异常附加信息:调用线程无法访问此对象,因为另一个线程拥有它。
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(() => ClientStart(dispatcher));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
private void ClientStart(Dispatcher dispatcher)
{
....
并更改了打印方法:
dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
w.GetMessageBox()
.AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));
使用Application.Current.Dispatcher
解决了
答案 0 :(得分:4)
始终警惕Dispatcher.CurrentDispatcher
,因为它将返回一个对象,用于在CURRENT线程上调度 - 可能不是UI。您想要(通常几乎总是想要)UI线程调度程序。
你可以通过Application.Current.Dispatcher
获得它,它总是返回UI线程调度程序。
令人沮丧的是,这些电话看起来如此相似......
[如果你在主窗口,你只需拨打Dispatcher
,但可能不是你的情况]
答案 1 :(得分:1)
来自MSDN上的Dispatcher.BeginInvoke
Method页:
在WPF中,只有创建
DispatcherObject
的线程才能访问该对象
因此,如果您首先从后台线程调用Dispatcher
,那么它只能在该后台线程上运行。而不是那样,确保在UI线程上“初始化”您的Dispatcher
对象:
Dispatcher = Dispatcher.CurrentDispatcher;
来自MSDN上的Dispatcher
Class页:
如果您尝试获取当前线程的
CurrentDispatcher
并且Dispatcher
未与该线程关联,则将创建Dispatcher
。
然后将对该UI线程Dispatcher
的引用传递给后台线程,这将使您能够从后台线程再次访问UI线程。