Многопоточность: как обновить UI для указания на прогресс

Шаги:

  1. Использование внешний номер версии постепенного увеличения (при усилении непрерывного сервера интеграции как CruiseControl.NET, тогда это прибывает из маркировки сборки).
  2. Использование GlobalVersionInfo.cs (файл, ссылаемый ссылкой всеми проектами в Вашем решении), чтобы содержать текущую версию и обновить его на сборке с задачей AssemblyInfo от Сообщество MSBuild задачи.
  3. Волшебник Сценария инструмент командной строки от SDK.NET для обновления декларации ClickOnce, с помощью той же версии (см. -v и -mv переключатели).

BTW, хорошая премия - то, что, каждый раз, когда Вы автоматически публикуете более новую версию развертывания ClickOnce с помощью сценария интеграции, если Вы также определяете минимальную версию к mage.exe (то же как версия), тогда каждый пользователь будет обновлен автоматически на следующем запуске приложения.

6
задан Cœur 15 August 2017 в 05:46
поделиться

9 ответов

I don't think you specify the version of the CLR you are using, but you might check out the "BackgroundWorker" control. It is a simple way to implemented multiple threads.

The best part, is that it is a part of the CLR 2.0 and up

Update in response to your update: If you want to be able to update the progress in the UI -- for example in a progress bar -- the background worker is perfect. It uses an event that I think is called: ProgressChanged to report the status. It is very elegant. Also, keep in mind that you can have as many instances that you need and can execute all the instances at the same time (if needed).

In response to your question: You could easily setup an example project and test for your question. I did find the following, here (under remarks, 2nd paragraph from the caution):

If the operation raises an exception что ваш код не обрабатывает, BackgroundWorker перехватывает исключение и передает его в Обработчик событий RunWorkerCompleted, где он отображается как ошибка собственностью System.ComponentModel .. ::. RunWorkerCompletedEventArgs.

6
ответ дан 10 December 2019 в 00:42
поделиться

This page is quite a good summary of threading.

By the sound of it you probably don't need anything very complex - if you just start the task and then want to know when it has finished, you only need a few lines of code to create a new thread and get it to run your task. Then your UI thread can bumble along and check periodically if the task has completed.

0
ответ дан 10 December 2019 в 00:42
поделиться

Не забудьте создать своих делегатов для обновления пользовательского интерфейса, чтобы у вас не возникало проблем с перекрестными потоками и пользовательский интерфейс не зависал / блокировался

Также, если вам нужно много примечания / пункты питания / и т.д. и т.п.

Могу я предложить все конспекты лекций моего старшекурсника http://ist.psu.edu/courses/SP04/ist411/lectures.html

0
ответ дан 10 December 2019 в 00:42
поделиться

Параллельное программирование в Windows - ЛУЧШАЯ книга по этой теме из существующих. Написал Джо Даффи, известный гуру многопоточности Microsoft. Все, что вам нужно знать, и многое другое, от работы планировщика потоков Windows до .NET Parallels Extensions Library.

0
ответ дан 10 December 2019 в 00:42
поделиться

The best way for a total newcomer to threading is probably the threadpool. We'll probably need to know a little more about these parts to make more in depth recommendations

EDIT::
Since we now have a little more info, I'm going to stick with my previous answer, it looks like you have a loads of tasks which need doing, the best way to do a load of tasks is to add them to the threadpool and then just keep checking if they're done, if tasks need to be done in a specific order then you can simply add the next one as the previous one finishes. The threadpool really is rather good for this kind of thing and I see no reason not to use it in this case

0
ответ дан 10 December 2019 в 00:42
поделиться

Ссылка Джейсона - хорошая статья. Вам нужно знать, что пользовательский интерфейс может быть обновлен только основным потоком пользовательского интерфейса, вы получите исключения между потоками, если попытаетесь сделать это в рабочем потоке. Элемент управления BackgroundWorker может помочь вам в этом с событиями, но вам также следует знать о Control.Invoke (или Control.Begin / EndInvoke). Это можно использовать для выполнения делегатов в контексте потока пользовательского интерфейса.

Также вы должны прочитать о проблемах доступа к одному и тому же коду / переменным из разных потоков, некоторые из этих проблем могут привести к ошибкам, которые являются прерывистыми и сложными.

Следует отметить, что ключевое слово volatile гарантирует только «свежесть» доступа к переменной, например, оно гарантирует, что каждое чтение и запись переменной будет производиться из основной памяти, а не из кэша потока или процессора или другой «особенности» модели памяти. Это не останавливает такие проблемы, как прерывание потока другим потоком во время процесса чтения-обновления-записи (например, изменение значения переменных). Это вызывает ошибки, когда 2 потока имеют разные (или одинаковые) значения для переменной, и может привести к таким вещам, как потеря значений, 2 потока, имеющие одинаковое значение для переменной, когда они должны иметь разные значения и т. Д. блокировка / монитор (или другой метод синхронизации потоков, дескрипторы ожидания, блокированное увеличение / уменьшение и т. д.) для предотвращения этих типов проблем, которые гарантируют, что только один поток может получить доступ к переменной. (Монитор также имеет то преимущество, что он неявно выполняет энергозависимое чтение / запись)

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

Matt

0
ответ дан 10 December 2019 в 00:42
поделиться

Распределение потоков в C # от Джозефа Альбахари неплохо.

4
ответ дан 10 December 2019 в 00:42
поделиться

В Typemock есть новый инструмент под названием Racer , помогающий решать проблемы с многопоточностью. Это немного продвинуто, но вы можете получить помощь на их форуме и на других онлайн-форумах (что странно приходит в голову, это stackoverflow :-))

0
ответ дан 10 December 2019 в 00:42
поделиться

Я тоже новичок в многопоточности, но я согласен с Фрэнком, что фоновый воркер, вероятно, является лучшим вариантом. Он работает через подписки на события. Вот основы того, как вы его использовали.

  • Сначала создайте экземпляр нового фонового рабочего.
  • Подписанные методы в вашем коде на основные события фоновых рабочих:
    • DoWork: он должен содержать любой код, который требует много времени для обработки
    • ProgressChanged: вызывается всякий раз, когда вы вызываете ReportProgress () изнутри метода, подписанного на DoWork
    • RunWorkerCompleted: вызывается, когда метод DoWork завершен

Когда вы будете готовы запустить трудоемкий процесс, вы вызываете метод RunAsync () фонового рабочего. Это запускает метод DoWork в отдельном потоке, который затем может сообщать о своем прогрессе через событие ProgressChanged. После его завершения будет вызван RunWorkerComplete.

Метод события DoWork также может проверить, запрашивал ли пользователь каким-то образом отмену процесса (был вызван CanceLAsync ())), проверяя значение свойства CancelPending.

0
ответ дан 10 December 2019 в 00:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: