Подсчет потоков в консольном приложении c#

#c# #visual-studio #reference #backgroundworker

#c# #visual-studio #ссылка #backgroundworker

Вопрос:

В настоящее время я переношу код из приложения WPF в консольное приложение. В viewmodel wpf я сохранил целочисленную переменную (int NumberOfThreads), и я могу манипулировать ею, увеличивая при создании потоков и уменьшая при вызове метода RunWorkerCompleted. В консольном приложении это немного сложнее, поскольку я знаю, что объявление общедоступной статической переменной, имитирующей глобальную переменную, является большим «нет».

Мне также нужно передать в DoWork имя файла, журнал и bool, которые указывают, есть ли ошибки в журнале, вместе с целым числом потоков. Это то, что у меня есть до сих пор:

  private static void ProcessFile(string file, CwiLogger log, ref int numberOfThreads, bool hasErrors)
        {
            Interlocked.Increment(ref numberOfThreads);
            var processFileBackgroundWorker = new BackgroundWorker();
            processFileBackgroundWorker.DoWork  = new DoWorkEventHandler(processFileBackgroundWorker_DoWork);
            processFileBackgroundWorker.RunWorkerCompleted  = new RunWorkerCompletedEventHandler
                    (processFileBackgroundWorker_RunWorkerCompleted);
            var processFileTuple = new Tuple<string, CwiLogger, int, bool>(file, log, numberOfThreads, hasErrors);
            processFileBackgroundWorker.RunWorkerAsync(processFileTuple);
        }
  

таким образом, я полагаю, что смогу распаковать кортеж в функции DoWork. а затем передайте другой кортеж методу RunWorkerCompleted.

Однако я предполагаю, что при этом они передаются не по ссылке на функцию DoWork, и что когда я передаю их в e.Results, это также будет по значению, а не по ссылке. Поэтому, когда я уменьшаю значение в RunWorkerCompleted, это будет уменьшать копию.

Комментарии:

1. Вы думали об использовании TPL и объединении всей работы в List<Task> ?

2. Простите мое невежество, поскольку я довольно новичок в этом, но я не вижу, как это решило бы мою проблему.

3. Вы не можете упаковать ref значение в кортеж, и работа с ref в целом является головной болью (делегатам они тоже не нравятся). Создайте новый ThreadCounter класс, который обертывает счетчик и передает его вместо этого, или (если вам на самом деле не нужно изменять его в клиентском коде) Func<int> , который выдает значение по требованию (получая его из некоторого общего поля). Однако обратите внимание, что вы перепрыгиваете через множество обручей, чтобы избежать того, что все еще является глобальным, просто немного лучше инкапсулированным, чем большинство. На самом деле это мало что добавляет.

4. @JacobAlley если у вас есть время, загляните на страницу TPL MSDN ( msdn.microsoft.com/en-us/library/dd460717 (v=против110).aspx ). По сути, это абстрагирует использование Thread от того, что называется Task . Это очень упрощает выполнение асинхронной работы и обработку того, что происходит до и после выполнения работы. Попробуйте найти учебное пособие, а затем проведите аналогию между учебным пособием и вашим приложением. Task по сути, это замена для BackgroundWorker .

5. спасибо, да, это было определенно полезно и намного более интуитивно