使用带有输入参数和结果的Task

本文关键字:结果 Task 参数 输入 | 更新日期: 2023-09-27 18:06:03

所以,我想使用新的任务类(几年前我会使用BackgroundWorker)做以下事情,但我不确定如何让它工作。对不起,我生疏了…

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.        
}

希望这是有意义的?

从我从搜索中看到的,看起来Lambda表达式使用得最频繁。我从来没有真正使用过它们,所以我(一开始)试图找到一种更冗长的方式来完成同样的事情。

谢谢!

使用带有输入参数和结果的Task

最好的选择是使用像这样的lambda表达式:

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

但是,在循环中这样做要小心。如果正在使用的变量没有在运行任务的循环迭代中初始化,那么它可能会发生变化并产生意想不到的结果。为了避免问题,在循环内重新初始化变量,如下所示:

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

在第一个示例中,doStuff()将把i解析为任务运行时的值,而不是调用Task.Run()时的值。将值复制到当前作用域中创建的变量将解决这个问题,这就是我们在第二个示例中所做的。(显然,这对引用对象不起作用)

如果你安装了Resharper,如果它看到了,它应该会警告你。

从我从搜索中看到的,看起来Lambda表达式使用得最频繁。我从来没有真正使用过它们,所以我(一开始)试图找到一种更冗长的方式来完成同样的事情。

使用Lambdas !但是,嘿,如果你不想,就使用普通的老方法;)

// :)
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.        
}