Несколько мелких вопросов по C#

Рейтинг: 0Ответов: 1Опубликовано: 30.09.2014

Добрый день. Решил не городить несколько тем, а написать все в одну.

1) Есть ли принципиальные различия между: Task.Factory.StartNew и Task.Run?

2) Не могли бы простым языком объяснить практическое применение ключевого слова volatile? На msdn есть пример, но смысл его плохо до меня доходит.

3) В последнем примере (для .NET 4.0) исследования, проведенного @VladD, описывается метод:

void Consumer()
{
    foreach (var s in q.GetConsumingEnumerable())
    {
        Console.WriteLine("Processing: {0}", s);
        Thread.Sleep(2000);
        Console.WriteLine("Processed: {0}", s);
    }
}

Я использовал подобную реализацию для записи с разных потоков в один файл, примерно так:

private void ErrorWrite()
    {
        foreach (var item in Error_Collection.GetConsumingEnumerable())
        {
            using (StreamWriter sw = File.AppendText(Path_Error_File))
            {
                sw.WriteLine(item);
            }
        }

        Thread.Sleep(1000);
    }

Код работает стабильно, но вот данный код работает через раз, причем при увеличении числа потоков - практически совсем перестает работать:

private void ErrorWrite()
    {
        using (StreamWriter sw = File.AppendText(Path_Error_File))
        {
            foreach (var item in Error_Collection.GetConsumingEnumerable())
            {
                    sw.WriteLine(item);
            }
        }
     Thread.Sleep(1000);
    }

С чем подобное может быть связано?

Ответы

▲ 5Принят
  1. Особой разницы нет - Run - это "сокращенная" версия StartNew с null, переданным в качестве токена отмены таска

  2. volatile нужен для того, чтобы сообщить CLR, что член, помеченный этим модификатором, может быть использоован одновременно из нескольких потоков. Зачем это нужно? Дело в том, что в силу некоторых хитрых колдунств, связанных с оптимизацией многопоточного кода, инструкции в целях оптимизации могут, например, "поменяться местами". В случае однопоточного выполнения (то есть в подавляющем большинстве случаев) это не будет иметь никаких последствий. Однако же логика исполнения программы с учетом нескольких потоков становится гораздо сложнее, и подобные оптимизации уже не проходят бесследно, в результате чего ваш код будет работать не так, как ожидалось. Так вот volatile позволяет это предотвратить.