0

So, I would like to use the new Task class (years ago I would use BackgroundWorker) to do the following but I'm unsure how to get it working. Apologies, I'm rusty...

internal bool DoThisThing(string input) {...} // Takes a while.

private void toggleButton_Click(object sender, RoutedEventArgs e)
{
    string toggleButtonName = "hi!";

    Func<string, bool> delToUse = new Func<string, bool>(DoThisThing); // Delgate of appropriate type

    Task<bool> task = new Task<bool>(delToUse);  // Doesn't like this. Something I can do instead?

    ... // do other things for a while

    // Task takes a while, don't want to block UI thread, use Task.
    task.Start(toggleButtonName);   // Looks like Start method doesn't allow input parameters for the assigned delegate like this. How can I accomplish something similar?

    ... keep on going and let Task finish. Maybe check the result, maybe not.        
}

Hopefully that makes some sense?

From what I've seen from searching, it looks like Lambda expressions are used most frequently. I never really used them much so I was (at first) trying to find a more verbose way of accomplishing the same thing.

Thanks!

2 Answers 2

1

Best option is using a lambda expression like this:

string toggleButtonName = "hi!";
Task<bool> task = Task.Run(() => delToUse(toggleButtonName));

However, be careful about doing so while in a loop. If the variable you are utilizing isn't initialized in the iteration of the loop you ran the task in, it might change and produce unintended results. To avoid issues, reinitialize the variable inside the loop like so:

for(int i = 0; i < 10; i++)
{
    // Don't do this!!!!
    Task<int> task = Task.Run(() => doStuff(i));

    // Do this!!!
    string j = i;
    Task<int> task = Task.Run(() => doStuff(j));
}

In the first example, doStuff() will resolve i to whatever value it's at when the task is ran, not the value it's at when you called Task.Run(). Copying the value to a variable created in the current scope will resolve this issue, which is what we did in the second example. (Obviously, this doesn't work the same for reference objects)

If you have Resharper installed, it should actually warn you about this if it see's it.

Sign up to request clarification or add additional context in comments.

Comments

0

From what I've seen from searching, it looks like Lambda expressions are used most frequently. I never really used them much so I was (at first) trying to find a more verbose way of accomplishing the same thing.

Use Lambdas! But hey, if you don't want to, just use plain-old-boring methods ;)

// :)
internal bool DoThisThing_ShouldBeALambda() {
    string toggleButtonName = "hi!";
    return DoThisThing(toggleButtonName);
}

internal bool DoThisThing(string input) {...} // Takes a while.

private void toggleButton_Click(object sender, RoutedEventArgs e)
{
    Task<bool> task = new Task<bool>(DoThisThing_ShouldBeALambda); 

    // ... do other things for a while

    // Task takes a while, don't want to block UI thread, use Task.
    task.Start();

    // ... keep on going and let Task finish. Maybe check the result, maybe not.        
}

1 Comment

Any luck? Does using a method rather than a lambda expression seem OK to you?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.