Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Winforms to WPF conversion: BeginInvoke to what?

Here's my old code from 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");
        }
    }

Is there an easy way to convert this to be WPF friendly? So far, I have:

   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");
            });
        }
    }

But that second 'delegate' call fails. How can I invoke this delegate? I suppose I can go through the whole making a delegate method, making an instance of the delegate method, invoking that particular instance, etc, but I thought the whole point of these anonymous delegates was to avoid that hassle. Plus, my old winforms code has that first implementation all over the place, so I'd really like to avoid having to de-anonymize all my delegates.

Edit: I can try to use the MethodInvoker like I was before, but then the compiler gets confused. MethodInvoker is part of System.Windows.Forms, so using that approach doesn't work. As in:

    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");
            }));
        }
    }

That use of MethodInvoker is not kosher. Is there a separate implementation of it, or some other way to use the same behavior?

like image 228
mmr Avatar asked Apr 16 '09 22:04

mmr


2 Answers

System.Windows.Forms.MethodInvoker is simply a Delegate that take no parameters and returns void. In WPF, you can just replace it with System.Action. There are also other built-in Delegates that accept parameters, return values, or both.

In your case,

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

becomes

ValueLabel.Dispatcher.BeginInvoke(new Action(delegate() {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }));
like image 96
mjeanes Avatar answered Oct 17 '22 11:10

mjeanes


I think you need to change the signature of the delegate:

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

Also, look up using the BackgroundWorker component. Not just for wpf but also for the winform async operations.

like image 31
ChrisPelatari Avatar answered Oct 17 '22 10:10

ChrisPelatari