c#wpf dispatcher.beginInvoke冻结
我正在开发一个与服务器通信的应用程序c#wpf dispatcher.beginInvoke冻结,c#,wpf,freeze,dispatcher,C#,Wpf,Freeze,Dispatcher,我正在开发一个与服务器通信的应用程序 thread = new Thread(new ThreadStart(ClientStart)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); private void ClientStart() { tcpClient = new TcpClient(ip,3000); stream = tcpCli
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)));
}
稍后,我需要将结果打印到messagebox。我知道我必须使用Dispatcher,因为我在另一个线程中工作,但即使我使用beginInvoke方法,我的应用程序也会冻结
根据谢里登的回答进行编辑:
现在我得到:
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)));
使用MSDN上的页面中的应用程序.Current.Dispatcher
解决:
在WPF中,只有创建DispatcherObject
的线程才能访问该对象
因此,如果首先从后台线程调用调度程序
,那么它只能在该后台线程上运行。相反,请确保“初始化”UI线程上的Dispatcher
对象:
Dispatcher = Dispatcher.CurrentDispatcher;
从MSDN上的页面:
如果尝试获取当前线程的CurrentDispatcher
,并且Dispatcher
未与该线程关联,则将创建Dispatcher
然后,将对该UI线程的引用Dispatcher
传递到后台线程将使您能够从后台线程再次访问该UI线程。从MSDN上的页面:
在WPF中,只有创建DispatcherObject
的线程才能访问该对象
因此,如果首先从后台线程调用调度程序
,那么它只能在该后台线程上运行。相反,请确保“初始化”UI线程上的Dispatcher
对象:
Dispatcher = Dispatcher.CurrentDispatcher;
从MSDN上的页面:
如果尝试获取当前线程的CurrentDispatcher
,并且Dispatcher
未与该线程关联,则将创建Dispatcher
然后,将对该UI线程的引用
Dispatcher
传递到后台线程将使您能够从后台线程再次访问UI线程。始终要小心Dispatcher.CurrentDispatcher
,因为这将返回一个对象,以便在当前线程上进行调度,而该对象可能不是UI。您需要(通常几乎总是需要)UI线程调度程序
您可以通过Application.Current.Dispatcher
获得它,它总是返回UI线程调度程序
很遗憾这些电话看起来很相似
[如果您在主窗口中,您可以直接调用
Dispatcher
,但这可能不是您的情况]始终要小心Dispatcher.CurrentDispatcher
,因为这将返回一个对象,以便在当前线程上进行调度,而该对象可能不是UI。您需要(通常几乎总是需要)UI线程调度程序
您可以通过Application.Current.Dispatcher
获得它,它总是返回UI线程调度程序
很遗憾这些电话看起来很相似
[如果您在主窗口中,您可以直接调用
Dispatcher
,但这可能不是您的情况]我相信在MessageBox上打印不需要调用UIT Dispatcher线程只是一个线程。它只能按顺序处理事情。如果调用Dispatcher.Invoke,那么您的委托将被添加到队列中,并根据优先级进行处理。这意味着,在处理您的委托时,调度程序将无法发送消息,因此您的UI将被锁定。stream.Read需要多长时间才能完成?while(true)语句的循环很紧,因此您可能无法提供足够的资源来运行消息泵。我相信在MessageBox上打印并不需要调用UIT。dispatcher线程只是一个线程。它只能按顺序处理事情。如果调用Dispatcher.Invoke,那么您的委托将被添加到队列中,并根据优先级进行处理。这意味着,在处理您的委托时,调度程序将无法发送消息,因此您的UI将被锁定。stream.Read需要多长时间才能完成?while(true)语句的循环很紧,因此您可能无法产生足够的资源来运行消息泵。