im работает над приложением, которое общается с сервером.
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, потому что im работает в другом потоке, но мое приложение зависает, даже если я использую метод beginInvoke.
Редактировать на основе ответа Шеридан:
теперь im получение: необработанное исключение типа "Исключение System.InvalidOperationException" произошло в WindowsBase.dll
Дополнительная информация: вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток.
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
Всегда будьте осторожны с Dispatcher.CurrentDispatcher
как это вернет объект для отправки в поток CURRENT, что может и не быть пользовательским интерфейсом. Вы хотите (и обычно почти всегда хотите) диспетчер потоков пользовательского интерфейса.
Вы можете получить это через Application.Current.Dispatcher
который всегда возвращает диспетчер потоков пользовательского интерфейса.
Его отвращение, что эти вызовы выглядят так похожими...
[Если вы находитесь в главном окне, вы можете просто вызвать Dispatcher
но, вероятно, это не так)
На странице Метод Dispatcher.BeginInvoke
в MSDN:
В WPF только поток, создавший
DispatcherObject
может получить доступ к этому объекту
Поэтому, если вы сначала вызвали Dispatcher
из своего фонового потока, тогда он может работать только в этом фоновом потоке. Вместо этого убедитесь, что вы инициализируете свой объект Dispatcher
в потоке пользовательского интерфейса:
Dispatcher = Dispatcher.CurrentDispatcher;
На странице Dispatcher
класс в MSDN:
Если вы попытаетесь получить
CurrentDispatcher
для текущего потока, иDispatcher
не связан с потоком, будет созданDispatcher
.
Затем, передав ссылку на этот Dispatcher
потоков пользовательского интерфейса в фоновый поток, вы сможете снова получить доступ к потоку пользовательского интерфейса из фонового потока.