WPF многопоточность - PullRequest
       8

WPF многопоточность

2 голосов
/ 04 февраля 2010

Я ломаю голову, пытаясь заставить работать многопоточность так, как хочу в WPF

У меня есть объект (с одноэлементным именем), называемый Manager, который выполняет много операций обработки и поиска. Я хочу, чтобы он запускался в отдельном потоке от пользовательского интерфейса. Пользовательский интерфейс будет вызывать методы в Диспетчере для обработки и запуска событий, на которые пользовательский интерфейс должен реагировать

Я конвертирую это приложение из форм Windows, где я не думаю, что это было проблемой, поскольку событие textbox автоматически запускалось в другом потоке. Не так в WPF, где, кажется, все остается в потоке пользовательского интерфейса.

Как заставить объект "жить" в другом потоке, а затем как я вызываю его методы. Я попытался создать его в новом потоке, используя это в конструкторе Window

        Thread managerThread = new Thread(new ThreadStart(ManagerStartingPoint));
        managerThread.SetApartmentState(ApartmentState.STA);
        managerThread.IsBackground = true;
        managerThread.Start();

и

private void ManagerStartingPoint()
    {
        ManagerSingleton.Manager = new Manager();
        MediatorSingleton.Mediator = new Mediator();
    }

В текстовом поле с текстовым событием я вызываю Manager.SetItemText (e.Value), который логически должен вызываться в новом потоке, верно? Тем не менее, когда я печатаю, и событие запускает UI "заикается", и это влияет на ввод текста в текстовом поле. Нужно ли вызывать метод асинхронно или как?

Ответы [ 2 ]

4 голосов
/ 04 февраля 2010

Вы просто создаете эти объекты в фоновом режиме; это на самом деле не имеет значения. Вам нужно вызывать ваши методы в фоновом режиме:

public YourTextBox_TextChanged(...) {
    var bw = new BackgroundWorker();

    bw.DoWork += (sender, args) => {
        // do your lengthy stuff here -- this will happen in a separate thread
        Manager.SetItemText(e.Value)
    }

    bw.RunWorkerCompleted += (sender, args) => {
        if (args.Error != null)  // if an exception occurred during DoWork,
            MessageBox.Show(args.Error.ToString());  // do your error handling here

        // Do whatever you want to do after the SetItemText has completed.
        // We are back in the UI thread here.
        ...
    }

    bw.RunWorkerAsync(); // start the background worker
}

PS: Убедитесь, что ваш метод Manager.SetItemText поточно-ориентирован! При использовании фоновых потоков вполне возможно, что несколько экземпляров Manager.SetItemText будут выполняться параллельно (если второе событие TextChanged наступает до первый SetItemText был завершен).

3 голосов
/ 04 февраля 2010

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

Экземпляры объектов не "живут" в потоках. Экземпляр - это просто указатель на структуру в памяти. Тот факт, что вы создаете экземпляр в потоке A , не означает, что все методы в этом экземпляре будут выполняться в потоке A .

То, что вы хотите сделать, - это создать класс, который вы можете вызывать из любого потока, но который использует свой собственный внутренне управляемый поток (или некоторую такую ​​конструкцию) для выполнения выполнения.

Ваш «менеджер» должен инкапсулировать поток или использовать ThreadPool для выполнения вашей «обработки». Когда все будет готово, менеджер должен будет связаться с вашим пользовательским интерфейсом (используя Dispatcher для перенаправления этого сообщения обратно в поток пользовательского интерфейса), указывая, что он завершил выполнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...