Преобразование Winforms в WPF: BeginInvoke к чему? - PullRequest
10 голосов
/ 17 апреля 2009

Вот мой старый код из WinForms:

    private void ValueChanged(double inValue1, double inValue2) {
        //only manual mode for this driver, so that's easy.
        if (ValueLabel.InvokeRequired) {
            ValueLabel.Invoke(new MethodInvoker(delegate {
                ValueLabel.Text = (inValue1* inValue2/ 1000).ToString("f1");
            }
                ));
        }
        else {
            ValueLabel.Text = (inValue1* inValue2/ 1000).ToString("f1");
        }
    }

Есть ли простой способ конвертировать его в WPF? Пока что у меня есть:

   private void KVPValueChanged(double inValue1, double inValue2) {
        if (ValueLabel.Dispatcher.Thread == Thread.CurrentThread){
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        } else {
            ValueLabel.Dispatcher.BeginInvoke(delegate {
                ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
            });
        }
    }

Но этот второй вызов делегата не проходит. Как я могу вызвать этого делегата? Я предполагаю, что могу пройти весь процесс создания метода делегата, создания экземпляра метода делегата, вызова этого конкретного экземпляра и т. Д., Но я думал, что весь смысл этих анонимных делегатов состоял в том, чтобы избежать этой проблемы. Кроме того, мой старый код winforms имеет эту первую реализацию повсеместно, поэтому я бы очень хотел избежать анонимизации всех моих делегатов.

Редактировать: Я могу попытаться использовать MethodInvoker, как и раньше, но тогда компилятор запутается. MethodInvoker является частью System.Windows.Forms, поэтому использование этого подхода не работает. Как в:

    private void ValueChanged(double inValue1, double inValue2) {
        if (ValueLabel.Dispatcher.Thread == Thread.CurrentThread) {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }
        else {
            ValueLabel.Dispatcher.BeginInvoke(new System.Windows.Forms.MethodInvoker(delegate {
                ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
            }));
        }
    }

То, что использование MethodInvoker не является кошерным. Есть ли отдельная реализация или какой-то другой способ использовать то же поведение?

Ответы [ 2 ]

12 голосов
/ 17 апреля 2009

System.Windows.Forms.MethodInvoker - это просто делегат, который не принимает никаких параметров и возвращает void. В WPF вы можете просто заменить его на System.Action . Есть также другие встроенные делегаты, которые принимают параметры , возвращают значения или оба .

В вашем случае

ValueLabel.Dispatcher.BeginInvoke(new System.Windows.Forms.MethodInvoker(delegate {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }));

становится

ValueLabel.Dispatcher.BeginInvoke(new Action(delegate() {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }));
5 голосов
/ 17 апреля 2009

Я думаю, вам нужно изменить подпись делегата:

ValueLabel.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate(invalue1, invalue2){
    ValueLabel.Content = ...

Также ищите, используя компонент BackgroundWorker. Не только для wpf, но и для асинхронных операций winform.

...