Как запустить простой бит кода в новом streamе?

У меня есть немного кода, который мне нужно запустить в другом streamе, чем в графическом интерфейсе, поскольку он в настоящее время заставляет форму замораживаться, пока код работает (10 секунд или около того).

Предположим, что я еще никогда не создавал новый stream; что такое простой / базовый пример того, как это сделать на C # и с использованием .NET Framework 2.0 или новее?

Хорошим местом для начала чтения является Джо Альбахари .

Если вы хотите создать свой собственный stream, это будет так же просто, как и получается:

using System.Threading; new Thread(() => { Thread.CurrentThread.IsBackground = true; /* run your code here */ Console.WriteLine("Hello, world"); }).Start(); 

BackgroundWorker кажется, лучший выбор для вас.

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

 using System.ComponentModel; ... private void button1_Click(object sender, EventArgs e) { BackgroundWorker bw = new BackgroundWorker(); // this allows our worker to report progress during work bw.WorkerReportsProgress = true; // what to do in the background thread bw.DoWork += new DoWorkEventHandler( delegate(object o, DoWorkEventArgs args) { BackgroundWorker b = o as BackgroundWorker; // do some simple processing for 10 seconds for (int i = 1; i <= 10; i++) { // report the progress in percent b.ReportProgress(i * 10); Thread.Sleep(1000); } }); // what to do when progress changed (update the progress bar for example) bw.ProgressChanged += new ProgressChangedEventHandler( delegate(object o, ProgressChangedEventArgs args) { label1.Text = string.Format("{0}% Completed", args.ProgressPercentage); }); // what to do when worker completes its task (notify the user) bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler( delegate(object o, RunWorkerCompletedEventArgs args) { label1.Text = "Finished!"; }); bw.RunWorkerAsync(); } 

Заметка:

  • Я поместил все в один метод, используя анонимный метод C # для простоты, но вы всегда можете вывести их на разные методы.
  • Безопасно обновлять GUI в обработчиках ProgressChanged или RunWorkerCompleted . Однако обновление GUI от DoWork приведет к InvalidOperationException .

ThreadPool.QueueUserWorkItem довольно идеален для чего-то простого. Единственное предостережение – доступ к управлению из другого streamа.

 System.Threading.ThreadPool.QueueUserWorkItem(delegate { DoSomethingThatDoesntInvolveAControl(); }, null); 

Быстрая и грязная, но она будет работать:

Использование сверху:

 using System.Threading; 

простой код:

 static void Main( string[] args ) { Thread t = new Thread( NewThread ); t.Start(); } static void NewThread() { //code goes here } 

Я просто бросил это в новое консольное приложение для exmaple

Вот еще один вариант:

 Task.Run(()=>{ //Here is a new thread }); 

Попробуйте использовать class BackgroundWorker . Вы даете ему делегатов за то, что нужно запускать, и чтобы они были уведомлены о завершении работы. На странице MSDN, с которой я связан, есть пример.

Если вы хотите получить значение:

 var someValue; Thread thread = new Thread(delegate() { //Do somthing and set your value someValue = "Hello World"; }); thread.Start(); while (thread.IsAlive) Application.DoEvents(); 

Поместите этот код в функцию (код, который не может быть выполнен в том же streamе, что и GUI), и для запуска выполнения этого кода поставьте следующее.

Thread myThread= new Thread(nameOfFunction);

workerThread.Start();

Вызов функции запуска объекта streamа приведет к выполнению вызова функции в новом streamе.

Здесь, как можно использовать streamи с progressBar, просто для того, чтобы понять, как работают streamи, в форме есть три кнопки progressBar и 4:

  public partial class Form1 : Form { public Form1() { InitializeComponent(); } Thread t, t2, t3; private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; t = new Thread(birinicBar); //evry thread workes with a new progressBar t2 = new Thread(ikinciBar); t3 = new Thread(ucuncuBar); } public void birinicBar() //to make progressBar work { for (int i = 0; i < 100; i++) { progressBar1.Value++; Thread.Sleep(100); // this progressBar gonna work faster } } public void ikinciBar() { for (int i = 0; i < 100; i++) { progressBar2.Value++; Thread.Sleep(200); } } public void ucuncuBar() { for (int i = 0; i < 100; i++) { progressBar3.Value++; Thread.Sleep(300); } } private void button1_Click(object sender, EventArgs e) //that button to start the threads { t.Start(); t2.Start(); t3.Start(); } private void button4_Click(object sender, EventArgs e)//that button to stup the threads with the progressBar { t.Suspend(); t2.Suspend(); t3.Suspend(); } private void button2_Click(object sender, EventArgs e)// that is for contuniue after stuping { t.Resume(); t2.Resume(); t3.Resume(); } private void button3_Click(object sender, EventArgs e) // finally with that button you can remove all of the threads { t.Abort(); t2.Abort(); t3.Abort(); } } 
 // following declaration of delegate ,,, public delegate long GetEnergyUsageDelegate(DateTime lastRunTime, DateTime procDateTime); // following inside of some client method GetEnergyUsageDelegate nrgDel = GetEnergyUsage; IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null); while (!aR.IsCompleted) Thread.Sleep(500); int usageCnt = nrgDel.EndInvoke(aR); 

Чарльз ваш код (выше) неверен. Вам не нужно отжимать ожидание завершения. EndInvoke будет блокироваться до тех пор, пока не будет сигнализирован WaitHandle.

Если вы хотите заблокировать до завершения, вам просто нужно

 nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null)); 

или альтернативно

 ar.AsyncWaitHandle.WaitOne(); 

Но в чем смысл выдавать вызовы anyc, если вы блокируете? Вы можете просто использовать синхронный вызов. Лучшая ставка заключалась бы в том, чтобы не блокировать и пропускать лямбду для очистки:

 nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null); 

Следует иметь в виду, что вы должны позвонить EndInvoke. Многие люди забывают об этом и заканчивают утечку WaitHandle, так как большинство асинхронных реализаций освобождают waithandle в EndInvoke.

Если вы собираетесь использовать необработанный объект Thread, вам необходимо установить значение IsBackground как минимум, и вы также должны установить модель Threading Apartment (возможно, STA).

 public static void DoWork() { // do some work } public static void StartWorker() { Thread worker = new Thread(DoWork); worker.IsBackground = true; worker.SetApartmentState(System.Threading.ApartmentState.STA); worker.Start() } 

Я бы рекомендовал class BackgroundWorker, если вам нужно взаимодействие с пользовательским интерфейсом.

другой вариант, который использует delegates и пул streamов …

предполагая, что «GetEnergyUsage» – это метод, который принимает DateTime и другой DateTime в качестве входных аргументов и возвращает Int …

 // following declaration of delegate ,,, public delegate long GetEnergyUsageDelegate(DateTime lastRunTime, DateTime procDateTime); // following inside of some client method GetEnergyUsageDelegate nrgDel = GetEnergyUsage; IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null); while (!aR.IsCompleted) Thread.Sleep(500); int usageCnt = nrgDel.EndInvoke(aR); 

Существует много способов запуска отдельных streamов в .Net, каждый из которых имеет разные типы поведения. Вам нужно продолжить выполнение streamа после завершения работы GUI? Вам нужно передавать информацию между streamом и графическим интерфейсом? Нужен ли stream для обновления графического интерфейса? Должен ли stream выполнить одну задачу, а затем выйти или продолжить работу? Ответы на эти вопросы расскажут вам, какой метод использовать.

На веб-сайте Code Project есть хорошая статья асинхронного метода, которая описывает различные методы и предоставляет пример кода.

Обратите внимание, что эта статья была написана до того, как шаблон async / await и параллельная библиотека задач были представлены в .NET.

Как использовать фоновый stream для поиска файлов

Вы должны быть очень осторожны с доступом из других streamов к конкретным материалам GUI (это распространено для многих инструментов GUI). Если вы хотите что-то обновить в графическом интерфейсе из streamа обработки, проверьте этот ответ, который, как мне кажется, полезен для WinForms. Для WPF см. Это (он показывает, как касаться компонента в методе UpdateProgress (), поэтому он будет работать из других streamов, но на самом деле мне не нравится, что он не делает CheckAccess() прежде чем выполнять BeginInvoke через Dispathcer, см. И поиск CheckAccess в Это)

Смотрел .NET конкретную книгу по streamу и нашел ее (можно загрузить бесплатно). См. http://www.albahari.com/threading/ для получения дополнительной информации об этом.

Я считаю, что вы найдете то, что вам нужно для запуска выполнения в качестве нового streamа на первых 20 страницах, и у него есть еще много (не уверены в специфических fragmentах графического интерфейса, которые я подразумеваю строго для streamовой передачи). Был бы рад услышать, что сообщество думает об этой работе, потому что я читаю эту. На данный момент для меня это выглядит довольно аккуратно (для отображения специальных методов и типов .NET для streamовой передачи). Также он охватывает .NET 2.0 (а не древний 1.1), что я действительно ценю.

Я бы рекомендовал посмотреть на Power Threading Library Джеффа Рихтера и, в частности, на IAsyncEnumerator. Взгляните на видео в блоге Чарли Калверта, где Рихтер просматривает его для хорошего обзора.

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

  • Ошибка при использовании Task.Factory
  • Темы и записи файлов
  • Что делает SynchronizationContext?
  • Максимальное количество streamов в приложении .NET?
  • Попытка запуска нескольких HTTP-запросов параллельно, но ограничена Windows (реестром)
  • Запуск нескольких streamов пользовательского интерфейса
  • Обновление ObservableCollection в отдельном streamе
  • Как приостановить / скрыть stream или процесс в Android?
  • Где я могу получить streamобезопасный CollectionView?
  • Как сделать мой ArrayList streamобезопасным? Другой подход к проблеме в Java?
  • Java Fork / Join vs ExecutorService - когда использовать какой?
  • Interesting Posts

    «Дроссельная» асинхронная загрузка в F #

    Проверка адресов с помощью API Карт Google

    HTML5 Холст фонового изображения

    Никакое соединение не может быть сделано, потому что целевая машина активно отказалась от него

    Автозаполнение Word из внутреннего документа

    Datagridview: Как установить ячейку в режиме редактирования?

    как настроить тень на просмотр в Android?

    Windows Task Manager эквивалентен для Mac OS X?

    Как запустить приложение после установки в проекте установки Visual Studio

    Как нарисовать хрустящую, непрозрачную линию волос в JavaFX 2.2?

    Какой инструмент я могу использовать для создания и развертывания изображений Windows 7?

    java.lang.RuntimeException: Ошибка предоставления результата ResultInfo {who = null, request = 1888, result = 0, data = null} для активности

    Являются ли частые перезагрузки в течение короткого периода времени повреждением моего компьютера?

    Фиксирование разрешений для файлов пользователей Mac, а не системы

    Лучший способ указать пробелы в операции String.Split

    Давайте будем гением компьютера.