Отображение модального окна во время работы BackgroundWorker без проблем с STA / MTA - PullRequest
3 голосов
/ 09 января 2012

Я работаю над приложением WPF.У меня есть метод времени, который я хочу запустить асинхронный через BackgroundWorker.Пока метод работает, я хочу отобразить модальное диалоговое окно «Пожалуйста, подождите ...», которое должно автоматически закрываться после завершения BackgroundWorker.

В настоящее время у меня очень мало опыта работы с BackgroundWorker или любым другиммногопоточное программирование.

Приведенный ниже код в настоящее время приводит к InvalidOperationException с сообщением "Вызывающим потоком должен быть STA, поскольку это требуется для многих компонентов пользовательского интерфейса."

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

Большое спасибо!

РЕДАКТИРОВАТЬ Просто чтобы уточнить - Идея состоит в том, что основной поток запускает BackgroundWorker, а затем показывает модальное диалоговое окно.Когда работник завершает работу, он закрывает модальное диалоговое окно.Когда модальное диалоговое окно закрывается, основной поток продолжается.

public class ImageResizer
{
    private BackgroundWorker worker;
    private MemoryStream ImageData { get; set; } // incoming data
    private public MemoryStream ResizedImageData { get; private set; } // resulting data
    private Dialogs.WorkInProgressDialog ProgressDialog;


    // Public interface, called by using class:
    public MemoryStream ReduceImageSize(MemoryStream imageData)
    {
        // injected data:
        this.ImageData = imageData;

        // init progress dialog window:
        ProgressDialog = new Dialogs.WorkInProgressDialog();

        // Start background worker that asyncronously does work
        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);            
        worker.RunWorkerAsync();

        // Show progress dialog. Dialog is MODAL, and must only be closed when resizing is complete
        ProgressDialog.ShowDialog(); // THIS LINE CAUSES THE INVALID OPERATION EXCEPTION

        // This thread will only continue when ProgressDialog is closed.

        // Return result
        return ResizedImageData;
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Call time consuming method
        ResizedImageData = ReduceImageSize_ActualWork();
    }

    // The actual work method, called by worker_DoWork
    private MemoryStream ReduceImageSize_ActualWork()
    {
        // Lots of code that resizes this.ImageData and assigns it to this.ResizedImageData
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        // Async work completed - close progress dialog
        ProgressDialog.Close();
    }
}

1 Ответ

2 голосов
/ 09 января 2012

Вы не можете вызвать ShowDialog из BackgroundWorker.Вы должны использовать Dispatcher, чтобы попросить поток пользовательского интерфейса выполнить его:

 this.Dispatcher.BeginInvoke(new Action(() => ProgressDialog.ShowDialog()));

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

...