2012-04-25 2 views
0

Когда я побежал этот кусок кодаИспользование задачи с. Net 4.0 vs. .Net 4.5?

 private void button1_Click(object sender, EventArgs e) 
    { 
     Start(sender, e); 
    } 

    private void Start(object sender, EventArgs e) 
    { 
     for (int i = 0; i < 5; i++) 
     { 
      System.Threading.Tasks.Task.Factory.StartNew(() => dosomething(i)); 
      Debug.WriteLine("Called " + i); 
     } 
     Debug.WriteLine("Finished"); 

    } 
    public void dosomething(int i) 
    { 
     Debug.WriteLine("Enters " + i); 
     lock (this) 
     { 
      Debug.WriteLine("Working " + i); 
      Thread.Sleep(100); 
     } 
     Debug.WriteLine("Done " + i); 
    } 

выход отличается от .Net версии 4.0 и 4.5. С повторением числа 4 5 я вижу, что значение причины i перемещается на 5 до выполнения некоторых из Выполняемых задач, но тот же код с 4.5 показывает другой вывод.

(выход побежал с VS 2010 .Net 4.0)

Called 0 
Called 1 
Enters 1 
Working 1 
Called 2 
Called 3 
Called 4 
Finished 
Enters 0 
Done 1 
Enters 5 
Working 0 
Working 5 
Done 0 
**Enters 5 
Working 5 
Done 5 
Enters 5 
Done 5 
Working 5 
Done 5** 

но когда я бежал с .Net 4.5 (VS 2011 бета) является результатом,

(выход побежал с VS 2011 бета. Net 4.5)

Enters 0 
Working 0 
Called 0 
Called 1 
Enters 2 
Called 2 
Enters 2 
Enters 3 
Called 3 
Called 4 
Finished 
Done 0 
Working 2 
Enters 5 
Done 2 
Working 3 
Done 3 
Working 5 
Done 5 
Working 2 
Done 2 

Не удалось увидеть изменения, выполненные с помощью задачи под CLR 4.5? Может кто-нибудь указать мне, какие изменения произошли с .Net 4.5.

ответ

0

Ваш код имеет race condition. Это означает, что он может вести себя по-разному, в зависимости от точного порядка операций.

И любые небольшие изменения могут повлиять на порядок операций, поэтому не случайно, что ваш код будет вести себя по-разному в разных версиях фреймворка. На самом деле, я ожидал бы, что он будет вести себя по-разному, когда будет работать несколько раз для той же версии .net.

+0

Я бы не стал беспокоиться о порядке, я только смотрю, что значение i делится между потоками с .Net 4.0, но не с .Net 4.5. – murali

+0

В обоих случаях переменная 'i' в' Start() 'используется совместно, и что именно происходит, зависит от порядка операций. – svick

+0

Спасибо за ваше время ... Итак, ваша точка в том, что с 4.5 нет изменений, результат отличается от порядка операций? Я так не думаю, по какой причине я говорю это? Если вы наблюдаете порядок действий с выходом, вы увидите только после кратковременной паузы, на значение влияет. и я тестировал несколько раз и все время, порядок отличается, но результат такой же, как показано выше ... – murali

1

Ваш код имеет состояние гонки. Предположим, что цикл завершается, прежде чем запускать какие-либо задачи. Это вполне возможно.

Тогда у меня будет значение 5 в все задач. Это ошибка.

Решение: Скопируйте i в локальную переменную цикла и используйте это локальное значение в лямбда задачи.

+0

Спасибо за ответ, я согласен с изменением кода System.Threading.Tasks.Task.Factory.StartNew ((объект o) => dosomething (i), i); работает нормально, мой вопрос заключается не в том, как заставить его работать, но в том, что было сделано с CLR 4.5? – murali

+0

@murali Этот вопрос не имеет смысла. Заказ просто неопределен и не требует согласованности между разными запусками в той же версии среды выполнения. – CodesInChaos

+0

Я думаю, что новая CLR более эффективна при запуске задач. Из-за этого изменился (недетерминистический) порядок. Кстати, это не неопределенное поведение. Он четко определен, но не детерминирован. – usr