Многопоточность WPF с аксессорами - PullRequest
1 голос
/ 12 октября 2010

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

В 3.5 winforms я сделал что-то вроде следующего при обновлении моего интерфейса через другой поток:

    public string SummaryTitle
  {
   get
   {
    if (IsHandleCreated && InvokeRequired)
    {
     IAsyncResult result = BeginInvoke(new Func<object, object[], object>(GetType().GetProperty("SummaryTitle").GetValue), this, null);
     return EndInvoke(result).ToString();
    }

    return myTextBox.Text.Trim();
   }
   set
   {
    if (IsHandleCreated && InvokeRequired)
    {
     BeginInvoke(new Action<object, object, object[]>(GetType().GetProperty("SummaryTitle").SetValue), this, value, null);
    }
    else
    {
     myTextBox.Text = value;
    }
   }
  }

Теперь с 4.0 WPF я пытаюсь смоделировать вышесказанное, но с новым Dispatcher (может быть, есть другой / лучший способ, кроме диспетчера?). Вот код прототипа, с которым я сейчас играю (я знаю, что в нем все еще есть проблемы, не связанные с нитями, пожалуйста, пока игнорируйте его), и он работает неправильно:

     public string SomeText
  {
   get {
    if(!myTextBox.Dispatcher.CheckAccess())
    {
     object o = myTextBox.Dispatcher.Invoke(new Func<object, object[], object>(GetType().GetProperty("SomeText").GetValue), this, null);
     return o != null ? Convert.String(o) :  "";
    }

    return myTextBox.Text.Trim(); 
   }
   set
   {
    if (!myTextBox.Dispatcher.CheckAccess())
    {
     myTextBox.Dispatcher.Invoke(new Action<object, object, object[]>(GetType().GetProperty("SomeText").SetValue),this, value, null);
     return;
    } 

    myTextBox.Text = value;
   }
  }

Буду признателен за любую помощь в том, как сделать функцию доступа WPF похожей на старый метод winforms 3.5.


РЕДАКТИРОВАТЬ: я больше смотрю на способ сделать аксессор в пользовательском интерфейсе для экранного элемента потокобезопасным, чем вызывающий поток или в частности прогрессбар. Метод доступа должен быть в состоянии выполняться из другой сборки или класса независимо от того, использует ли этот вызывающий класс Thread или BackgroundWorker. Кроме того, он должен держать воду для всех элементов пользовательского интерфейса, а не только индикатор выполнения. Таким образом, текстовое поле и т. Д. Также можно сделать потокобезопасным таким образом. Я обновил примеры, чтобы лучше передать мои проблемы.

Ответы [ 2 ]

1 голос
/ 12 октября 2010

Я все еще довольно новичок в WPF, но всякий раз, когда я использую диспетчер, я указываю, на каком уровне приоритета выполнить действие.Это определяет, когда действие на самом деле запускается

myControl.Dispatcher.BeginInvoke(DispatcherPriority.Render,
    new Action(delegate()
    {
        // Code to execute goes here
    }
));

Список PriorityLevels можно найти здесь

Похоже, вы пытаетесь обновить индикатор выполнения... Если ваша полоса привязана к чему-либо (скажем, к числу от 0 до 100), вы можете добавить вызов диспетчера в ваш длительный процесс и попросить его обновить номер.Привязка данных должна позаботиться об остальном.

0 голосов
/ 12 октября 2010

Я знаю, что вы заинтересованы в том, чтобы Dispatcher работал должным образом, но для чего-то подобного вы рассматривали использование BackgroundWorker ? Хотя это немного ограничивает приоритеты и тому подобное, оно, безусловно, упрощает выполнение вычислений в фоновом потоке при обновлении пользовательского интерфейса.

Вот поток SO , где я помог кому-то использовать BackgroundWorker.

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

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