2012-01-16 2 views
-4

Можно создать дубликат:
WPF and cross thread operationsThreading вопрос - окно не обновляется/реагировании

У меня возникли проблемы с окном в моем WPF приложение, отображающее, но не обновляет представление. При размещении курсора над открытым окном отображается значок загрузки, и окно не отвечает. Я думаю, что это, вероятно, связано с какой-то проблемой нитей, у меня недостаточно опыта.


Вот установка:

Моя основная программа запускается при запуске и создает и экземпляр окна MainWindow, который реализует пользовательский интерфейс (Iplayer). Затем основная программа запускает процесс, который переписывает с помощью IPlayer для выполнения какой-либо задачи, и идея состоит в том, что основная программа запрашивает действия из MainWindow, которая запрашивает у пользователя какой-то ввод и отображает результаты.

Я упрощу код для ясности. Предположим, что эта программа просто запускает своего рода болтовню.

class MainProgram 
{ 

    [STAThread] 
    static void main(string[] args) 
    { 
     MainWindow wdw = new MainWindw(); 
     Game g = new Game(wdw); 

     wdw.Show(); 
     g.RunGame(); 
    } 

} 

class Game 
{ 
    public IPlayer p; 
    Game(IPlayer) { this.p = p; } 

    public RunGame() 
    { 
     string r = GetResponse("How was your day?"); 

     ... 
    } 
} 


public partial class Human_Player : Window, IPlayer 
{ 
    public string GetResponse(string Question) 
    { 
     ShowQuestion(Question); 
     string r = GetResponse(); 
     DisplayResponse(r); 
     return r; 
    } 

    ... 
} 

Я дал работает RunGame() в отдельном потоке выстрел, как это:

Thread thread = new Thread(new ThreadStart(game.RunGame)); 
thread.Start(); 

но получил InvalidOperationException в ответ о том, «Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет «.

Любая помощь здесь будет оценена, так как я довольно новичок в этом материале. Спасибо заранее!


EDIT:

Просто чтобы прояснить, я не создавать новые темы в данный момент. Таким образом, я не думаю Я делаю многопоточность. Я пытаюсь запустить game.RunGame() в основном потоке после открытия окна. Метод runGame состоит из большого цикла, который вызывает метод в окне Human_Player, который изменяет пользовательский интерфейс.

Насколько я знаю, есть только две темы: - Главная тема - MainProgram и Game работают здесь. Я думаю, что окна тоже работают, но я могу ошибаться ... прошу пояснить - Rendering Thread - здесь отображается интерфейс.

+3

Просто [поиск исключения] (http://stackoverflow.com/search?q=The%20calling%20thread%20cannot%20access%20this%20object%20because%20a%20different%20thread%20owns%20it.) ... –

+0

некоторые рекомендации по потоку .NET: только обновляйте визуальные объекты в своем потоке. вы возитесь с MainWindow в отдельном потоке? –

+0

При многопоточности вы не можете напрямую получить доступ к чему-либо из потока пользовательского интерфейса. Какой объект выбрасывает это исключение? – jlafay

ответ

1

Argh, этот вопрос задают много раз ... Вы не можете обновить элемент управления графическим интерфейсом из другого потока, кроме потока Диспетчера, связанного с элементом управления. Вам нужно будет запустить код обновления с помощью Dispatcher.BeginInvoke, чтобы обновить графический интерфейс из правильной темы.

Если вы не используете код из другого потока, возможно, что ваш метод занимает слишком много времени для выполнения, что приводит к зависанию графического интерфейса, потому что поток событий заблокирован от принятия ввода пользователем.

+0

Не могу объяснить, как game.RunGame() находится в другом потоке, чем Human_Player окно? – marrithl2

+0

@ marrithl2: Хорошо, если вы не используете строку Thread thread = new Thread (новый ThreadStart (game.RunGame)); то это не на другой поток. Возможно, ваш метод слишком долго выполняется, что делает GUI зависанием. Попробуйте использовать секундомер и посмотрите. – Tudor

+0

Используется секундомер, и все, кажется, работает быстро. В классе Human_Player методы занимают менее миллисекунды. Метод runGame требует времени, потому что он запускает всю игру между двумя игроками, постоянно вызывая методы между ними. (Это на самом деле игра с линкором) – marrithl2

0

Похоже, что ваш игровой код работает в цикле и крадет все время обработки вашего пользовательского интерфейса. Не похоже, что вы отправляете управление своему диспетчеру.

Ваш игровой код не должен зацикливаться, он должен запускать итерацию один раз, а затем возвращать управление диспетчеру. Вам нужно создать таймер, который будет вызывать ваш игровой код через регулярные промежутки времени.

+0

это хорошая идея ... Мне нужно заглянуть в нее – marrithl2

Смежные вопросы