c # wpf - многопоточность - PullRequest
0 голосов
/ 04 мая 2018

Я использую C # wpf и хочу сделать снимок с камеры, а затем после завершения события вызвать - изменить некоторые элементы управления в MainWindow. Проблема в том, что событие вызывается в другом потоке, нежели основной, и для запуска моей функции NextState (с изменением некоторых элементов управления) он должен быть основным (в противном случае я получаю окно сообщения с предупреждением, и ничего не происходит). Вот мой код:

public partial class PhotoCapture : UserControl
{
    private bool ready;
    private System.Timers.Timer timer;
    private readonly Object lockObj = new Object();

    public PhotoCapture(PhotoCaptureState photoCaptureState)
    {
        InitializeComponent();

        ready = false;
        PictureManager.LoadCompleted += PictureManager_LoadCompleted;
        CameraManager.TakePicture();
        timer = new System.Timers.Timer(200);
        timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
        timer.Enabled = true;
    }

    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        bool change = false;
        lock(lockObj)
        {
            if (ready)
            {
                change = true;
            }
        }
        if (change)
        {
            MessageBox.Show("ready");
            timer.Enabled = false;
            PictureManager.LoadCompleted -= PictureManager_LoadCompleted;
            NextState();
        }
    }

    private void PictureManager_LoadCompleted()
    {
        lock (lockObj)
        {
            ready = true;
        }
    }

    private void NextState()
    {
        MainWindow wnd = (MainWindow)Application.Current.MainWindow;
        App app = (App)wnd.contentControl.Content;
        app.NextState();
    }
}

Что интересно, я получаю пару «готовых» окон сообщений и похоже, что NextStage вообще не выполняется. Я понятия не имею, почему он так себя ведет. Буду признателен за любую помощь

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вы правы, он выполняется в другом потоке.

Вы можете вызвать метод NextState() в главном потоке, используя Dispatcher.

Dispatcher.Invoke(() = > NextState());
0 голосов
/ 04 мая 2018

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

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

OR

Или вы можете попробовать использовать DispatcherTimer. DispatcherTimer запускает событие Tick в потоке пользовательского интерфейса, вы можете делать с ним все, что захотите. Вы можете увидеть примеры здесь .

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