-2

Как каждую секунду сверять значение переменной, которая меняется каждую секунду, с положением слайдера (WPF), и изменять в зависимости от значения этой самой переменной.

Ни dispatcher invoke, ни таймеры не помогли.

Появляется ошибка: "этот элемент уже занят основным потоком"

Grundy
  • 81,538
  • Причем тут dispatcher invoke? Вы в WPF программируете, а не WindowsForms. Изучайте MVVM. – Геннадий П Jun 27 '21 at 10:27
  • 2
    Вопросы с просьбами помочь с отладкой («почему этот код не работает?») должны включать желаемое поведение, конкретную проблему или ошибку и минимальный код для её воспроизведения прямо в вопросе. – aepot Jun 27 '21 at 10:33
  • По факту тут код мало чем поможет, но если формулировать совсем уж просто, то допустим, что мы имеем видеоконтрол (mediaElement) и слайдер Так вот, каким таким волшебным образом их можно синхронизировать? Чтобы слайдер отражал прогресс воспроизведения видео – JoeSmith_3950 Jun 28 '21 at 08:28
  • В общем я покопался в событиях и сделал по логике, всё заработало, использовал Dispatcher timer (DispatcherTimer _timer = new DispatcherTimer();) – JoeSmith_3950 Jun 28 '21 at 08:45
  • Ерундой вы страдаете. Вот скажите, как ваш вопрос объясняет нам то, что вам нужен прогресс воспроизведения видео/аудио? А не как. Код бы это нам и прояснил. Но вы ведь заигнорили наши просьбы и в итоге делаете костыль, ибо в WPF принято использовать привязки, вам достаточно тут привязаться лишь раз к одному свойству и радоваться жизни, но нет, таймер... Поглядите например это, думаю полезно будет вам. – EvgeniyZ Jun 28 '21 at 12:06

2 Answers2

-1

На просторах интернета нашел удобный класс для работы с объектами из разных потоков. Общий ответ используй класс Dispatcher.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace SP_Unsafe_DLL { public class SafeGuiWpf { public static object GetTag(Control C) { if (C.Dispatcher.CheckAccess()) return C.Tag; else return C.Dispatcher.Invoke(new Func<Control, object>(GetTag), C); } public static string GetText(TextBox TB) { if (TB.Dispatcher.CheckAccess()) return TB.Text; else return (string)TB.Dispatcher.Invoke(new Func<TextBox, string>(GetText), TB); } public static string GetText(ComboBox TB) { if (TB.Dispatcher.CheckAccess()) return TB.Text; else return (string)TB.Dispatcher.Invoke(new Func<ComboBox, string>(GetText), TB); }

    public static string GetText(PasswordBox TB)
    {
        if (TB.Dispatcher.CheckAccess()) return TB.Password;
        else return (string)TB.Dispatcher.Invoke(new Func&lt;PasswordBox, string&gt;(GetText), TB);
    }

    public static void SetText(TextBlock TB, string Str)
    {
        if (TB.Dispatcher.CheckAccess()) TB.Text = Str;
        else TB.Dispatcher.Invoke(new Action&lt;TextBlock, string&gt;(SetText), TB, Str);
    }
    public static void SetText(TextBox TB, string Str)
    {
        if (TB.Dispatcher.CheckAccess()) TB.Text = Str;
        else TB.Dispatcher.Invoke(new Action&lt;TextBox, string&gt;(SetText), TB, Str);
    }
    public static void AppendText(TextBox TB, string Str)
    {
        if (TB.Dispatcher.CheckAccess())
        {
            TB.AppendText(Str);
            TB.ScrollToEnd(); // scroll to end?
        }
        else TB.Dispatcher.Invoke(new Action&lt;TextBox, string&gt;(AppendText), TB, Str);
    }
    public static bool? GetChecked(CheckBox Ck)
    {
        if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
        else return (bool?)Ck.Dispatcher.Invoke(new Func&lt;CheckBox, bool?&gt;(GetChecked), Ck);
    }
    public static void SetChecked(CheckBox Ck, bool? V)
    {
        if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
        else Ck.Dispatcher.Invoke(new Action&lt;CheckBox, bool?&gt;(SetChecked), Ck, V);
    }
    public static bool GetChecked(MenuItem Ck)
    {
        if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
        else return (bool)Ck.Dispatcher.Invoke(new Func&lt;MenuItem, bool&gt;(GetChecked), Ck);
    }
    public static void SetChecked(MenuItem Ck, bool V)
    {
        if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
        else Ck.Dispatcher.Invoke(new Action&lt;MenuItem, bool&gt;(SetChecked), Ck, V);
    }
    public static bool? GetChecked(RadioButton Ck)
    {
        if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
        else return (bool?)Ck.Dispatcher.Invoke(new Func&lt;RadioButton, bool?&gt;(GetChecked), Ck);
    }
    public static void SetChecked(RadioButton Ck, bool? V)
    {
        if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
        else Ck.Dispatcher.Invoke(new Action&lt;RadioButton, bool?&gt;(SetChecked), Ck, V);
    }

    public static void SetVisible(UIElement Emt, Visibility V)
    {
        if (Emt.Dispatcher.CheckAccess()) Emt.Visibility = V;
        else Emt.Dispatcher.Invoke(new Action&lt;UIElement, Visibility&gt;(SetVisible), Emt, V);
    }
    public static Visibility GetVisible(UIElement Emt)
    {
        if (Emt.Dispatcher.CheckAccess()) return Emt.Visibility;
        else return (Visibility)Emt.Dispatcher.Invoke(new Func&lt;UIElement, Visibility&gt;(GetVisible), Emt);
    }
    public static bool GetEnabled(UIElement Emt)
    {
        if (Emt.Dispatcher.CheckAccess()) return Emt.IsEnabled;
        else return (bool)Emt.Dispatcher.Invoke(new Func&lt;UIElement, bool&gt;(GetEnabled), Emt);
    }
    public static void SetEnabled(UIElement Emt, bool V)
    {
        if (Emt.Dispatcher.CheckAccess()) Emt.IsEnabled = V;
        else Emt.Dispatcher.Invoke(new Action&lt;UIElement, bool&gt;(SetEnabled), Emt, V);
    }

    public static void SetSelectedItem(Selector Ic, object Selected)
    {
        if (Ic.Dispatcher.CheckAccess()) Ic.SelectedItem = Selected;
        else Ic.Dispatcher.Invoke(new Action&lt;Selector, object&gt;(SetSelectedItem), Ic, Selected);
    }
    public static object GetSelectedItem(Selector Ic)
    {
        if (Ic.Dispatcher.CheckAccess()) return Ic.SelectedItem;
        else return Ic.Dispatcher.Invoke(new Func&lt;Selector, object&gt;(GetSelectedItem), Ic);
    }
    public static int GetSelectedIndex(Selector Ic)
    {
        if (Ic.Dispatcher.CheckAccess()) return Ic.SelectedIndex;
        else return (int)Ic.Dispatcher.Invoke(new Func&lt;Selector, int&gt;(GetSelectedIndex), Ic);
    }

    delegate MessageBoxResult MsgBoxDelegate(Window owner, string text, string caption, MessageBoxButton button, MessageBoxImage icon);
    public static MessageBoxResult MsgBox(Window owner, string text, string caption, MessageBoxButton button, MessageBoxImage icon)
    {
        if (owner.Dispatcher.CheckAccess()) return MessageBox.Show(owner, text, caption, button, icon);
        else return (MessageBoxResult)owner.Dispatcher.Invoke(new MsgBoxDelegate(MsgBox), owner, text, caption, button, icon);
    }

    public static double GetRangeValue(RangeBase RngBse)
    {
        if (RngBse.Dispatcher.CheckAccess()) return RngBse.Value;
        else return (double)RngBse.Dispatcher.Invoke(new Func&lt;RangeBase, double&gt;(GetRangeValue), RngBse);
    }
    public static void SetRangeValue(RangeBase RngBse, double V)
    {
        if (RngBse.Dispatcher.CheckAccess()) RngBse.Value = V;
        else RngBse.Dispatcher.Invoke(new Action&lt;RangeBase, double&gt;(SetRangeValue), RngBse, V);
    }

    public static T CreateWindow&lt;T&gt;(Window Owner) where T : Window, new()
    {
        if (Owner.Dispatcher.CheckAccess())
        {
            var Win = new T(); // Window created on GUI thread
            Win.Owner = Owner;
            return Win;
        }
        else return (T)Owner.Dispatcher.Invoke(new Func&lt;Window, T&gt;(CreateWindow&lt;T&gt;), Owner);
    }

    public static bool? ShowDialog(Window Dialog)
    {
        if (Dialog.Dispatcher.CheckAccess()) return Dialog.ShowDialog();
        else return (bool?)Dialog.Dispatcher.Invoke(new Func&lt;Window, bool?&gt;(ShowDialog), Dialog);
    }

    public static void SetDialogResult(Window Dialog, bool? Result)
    {
        if (Dialog.Dispatcher.CheckAccess()) Dialog.DialogResult = Result;
        else Dialog.Dispatcher.Invoke(new Action&lt;Window, bool?&gt;(SetDialogResult), Dialog, Result);
    }

    public static Window GetWindowOwner(Window window)
    {
        if (window.Dispatcher.CheckAccess()) return window.Owner;
        else return (Window)window.Dispatcher.Invoke(new Func&lt;Window, Window&gt;(GetWindowOwner), window);
    }

} // END CLASS: SafeGuiWpf

}

  • Если костыль украсить драгоценными камнями - это будет красивый костыль, но всё равно костыль, не более. Но именно этот костыль выглядит реально ужасно. Не используйте его. На вопрос автора невозможно ответить конкретно, потому что сам вопрос не конкретный, можно только угадывать, именно поэтому ответа до сих пор нет. Есть такой класс Progress и IProgress интерфейс. В некоторых случаях он весьма удобно решает проблему типа той, что у автора. Поизучайте. – aepot Jun 27 '21 at 21:34
-2

В общем я покопался немного в событиях, написал такой код и всё заработало:

private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        _timer.Interval = TimeSpan.FromMilliseconds(1000);
        _timer.Tick += new EventHandler(sinchronyzeSliderAndVideoSession);
        _timer.Start();
    }
private void sinchronyzeSliderAndVideoSession(object sender, EventArgs e)
{
    VideoSlider.Value = VideoPlayer.Position.TotalSeconds;
}

  • и на все время подгрузил систему на обновление слайдера, надо не надо, обновляй(((( – Pavlo Khyzhniak May 29 '22 at 15:43