0

所以我的一些代码是这样异步调用的

Task.Run(() => DoSomethingAsync());

DoSomethingAsync 本身调用 DoSomething2Async 看起来像这样

private void DoSomething2Async()
{
    Something something = new Something(3);
    Random rand = new Random();
    for (int i = 0; i < 3; i++)
    {
        something.a = rand.Next(1000);

        var task = new Task<int>(()
            => Calculate());

        something.ContinueWith((t)
            => CalculateContinuation(something, task.Result));

        task.Start();
    }

    MessageBox.Show("Do Something2 is done");
}

这是Calculate() 方法

private int Calculate()
{
    for (int i = 0; i < 100000000; i++)
    {
        var a = 5; // imitate some job
    }

    return new Random().Next();
}

这是 CalculateContinuation() 方法

private void CalculateContinuation(Something something, int b)
{
    MessageBox.Show(something.a.ToString(), b.ToString());
}

这是类Something

class Something : ICloneable
{
    public int a;

    public Something(int aa)
    {
        a = aa;
    }

    public object Clone()
    {
        Something clone = new Something(a);

        return clone;
    }
}

如您所见Calculate,它被调用了 3 次,CalculateContinuation也将被调用 3 次,我想传递给 CalculateContinuation 2 个参数,一个是调用之前配置的对象(在这种情况下,它是某物的实例),第二个是方法的结果Calculate。现在的问题是,Calculate每次调用的结果都不同(因为它是随机的),并且每次调用的结果something.a也应该不同,因为它也是随机的,但是每次CalculateContinuation 被击中时,都指的是在循环的最终迭代DoSomething2Async。(如果它会在循环之前被击中,我认为它会引用当时配置的对象)。我的意思是我得到MessageBoxes的结果Calculate不同但something.a不是。这两天我一直在尝试解决这个问题,但我不知道该怎么做。我试图传递something我试图将somethings 添加到集合并在每次迭代中传递最后一个的克隆,但没有给我想要的结果。可能有人有这样的问题。在这种情况下有什么解决方案。提前致谢

编辑:

人类可读的代码

private void RegisterAllUsers()
{
    Person person = new Person(string.Empty);

    for (int i = 0; i < 3; i++)
    {
        person.Name = "Some name"; // different on each iteration

        // create registration task
        var registrationTask = new Task<bool>(()
            => RegisterUser(person));

        // assign continue with, first parameter is person itself and second is the result of RegisterUse
        registrationTask.ContinueWith((task)
            => RegistrationCallback(person, registrationTask.Result));

        registrationTask.Start();
    }
}

private bool RegisterUser(Person person)
{
    // do registration stuff

    return true; // or false if failes 
}

private void RegistrationCallback(Person person, bool succeded)
{
    // when this method executed the reference of person is whatever was set in RegisterAllUsers
    // for the last time, but i want to have reference to the user which was configured on each iteration

    // suppose 1st user is Steve 2nd is Bob and 3rd is Jack
    // when this methid is hit the name of the user is Jack on all 3 callbacks but the succeded parameter
    // is whatever the RegisterUser returned

    // update registered user's status
}

RegisterAllUsers 是这样调用的

Task.Run(() => RegisterAllUsers());
4

1 回答 1

1

关于您编辑的代码部分:

Person只有一个实例:person. 然后你开始你的循环i。循环person.Name为每个填充i,同时它开始一个任务。不幸的是,在任务开始之前,foreach 循环已经完成,并且person实例只包含最后分配的值。因此,您有三个计划任务,每个任务都采用一个person实例,该实例仅分配了最后一个值,Name因为我从问题描述中推断出Name依赖于它。i

要解决此问题,Person请为每个任务创建实例并j在循环中使用变量(闭包问题):

for (int i = 0; i < 3; i++)
{
    int j = i;
    Person person = new Person(string.Empty);
    person.Name = "Some name"; // depends on j this time rather on i
....
于 2013-11-07T08:27:10.303 回答