[英]c# wpf dispatcher.beginInvoke freeze
im working on an application which communicates with server. 我正在与服务器通信的应用程序上工作。
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)));
}
later i need to print result to a messagebox. 稍后我需要将结果打印到消息框。 I know i have to use Dispatcher, because im working in another thread, but my application freezes even if i use beginInvoke method. 我知道我必须使用Dispatcher,因为我在另一个线程中工作,但是即使我使用beginInvoke方法,我的应用程序也会冻结。
Edit based on Sheridan's answer : 根据Sheridan的答案进行编辑 :
now im getting: An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll 现在我正在获取:WindowsBase.dll中发生了类型为'System.InvalidOperationException'的未处理异常
Additional information: The calling thread cannot access this object because a different thread owns it. 附加信息:调用线程无法访问该对象,因为另一个线程拥有它。
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(() => ClientStart(dispatcher));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
private void ClientStart(Dispatcher dispatcher)
{
....
and changed print method: 并更改了打印方法:
dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
w.GetMessageBox()
.AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));
solved by using Application.Current.Dispatcher
通过使用Application.Current.Dispatcher
解决
Always be wary of Dispatcher.CurrentDispatcher
as that will will return an object for dispatching on the CURRENT thread - which may not be the UI. 始终要警惕Dispatcher.CurrentDispatcher
因为这将返回用于在CURRENT线程上分派的对象-可能不是UI。 You want (and generally almost always want) the UI thread dispatcher. 您想要(通常几乎总是想要)UI线程分派器。
You can get that through Application.Current.Dispatcher
Which always returns the UI thread dispatcher. 您可以通过Application.Current.Dispatcher
获得该信息,该Application.Current.Dispatcher
始终返回UI线程分派器。
Its frustating that these calls looks so similar... 令人沮丧的是这些调用看起来如此相似...
[If you are in the main window you can just call Dispatcher
but that probably not the case for you] [如果您在主窗口中,则可以仅致电Dispatcher
但实际情况并非如此]
From the Dispatcher.BeginInvoke
Method page on MSDN: 在MSDN上的Dispatcher.BeginInvoke
方法页面上:
In WPF, only the thread that created a
DispatcherObject
may access that object 在WPF中,只有创建DispatcherObject
的线程才能访问该对象
Therefore, if you first called the Dispatcher
from your background thread, then it can only run on that background thread. 因此,如果您首先从后台线程调用Dispatcher
,则它只能在该后台线程上运行。 Instead of that, ensure that you 'initialise' your Dispatcher
object on the UI thread: 而是要确保在UI线程上“初始化”您的Dispatcher
对象:
Dispatcher = Dispatcher.CurrentDispatcher;
From the Dispatcher
Class page on MSDN: 从MSDN上的Dispatcher
Class页面:
If you attempt to get the
CurrentDispatcher
for the current thread and aDispatcher
is not associated with the thread, aDispatcher
will be created. 如果您尝试获取当前线程的CurrentDispatcher
,并且Dispatcher
与该线程未关联,则将创建一个Dispatcher
。
Then passing a reference to that UI thread Dispatcher
to your background thread will enable you to access the UI thread again from the background thread. 然后,将对该UI线程Dispatcher
的引用传递给您的后台线程,将使您能够再次从后台线程访问UI线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.