簡體   English   中英

任務繼續弄亂了參考

[英]task continuation messes up the references

所以我的一些代碼像這樣異步調用

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

這是類的東西

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被命中時,某事指的是Something的實例它是在DoSomething2Async的循環的最終迭代中配置的。 (如果它將在循環之前被命中,我認為它將引用當時配置的對象)。 我的意思是我得到MessageBoxes ,其中Calculate結果是不同的,但是something.a沒有。 我已經嘗試解決了兩天,我不知道該怎么辦。 我試圖通過的克隆something我嘗試添加something s到收集和傳遞,最后在每次迭代,但沒有給我想要的結果。 可能有人遇到這樣的問題。 在這種情況下解決方案是什么? 提前致謝

編輯:

可讀代碼

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

關於您已編輯的部分代碼:

Person只有一個實例: person 然后,您從i開始循環。 循環填充每個i person.Name ,與此同時它開始執行任務。 不幸的是,在開始任務之前,前循環已完成,並且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
....

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM