Skip to content

How to create a thread ?

Gammasoft edited this page Nov 16, 2023 · 22 revisions

| xtd | News | Gallery | Examples | Downloads | Documentation | Wiki | Support | Sources | Project | Gammasoft |

There are many method to create a simple thread with xtd.

Using thread class instantiation

The usual first method is to create an instance of the xtd::threading::thread class and associate a delegate with it to run in the thread. You can start, join, detach, control the priority, get and set properties and manage the created thread.

#include <xtd/threading/thread>
#include <xtd/console>

using namespace xtd;
using namespace xtd::threading;

auto main()->int {
  auto value = 0;
  console::write_line("Start : value = {}", value);
  
  auto some_thread = thread {[&] {
    // Do some work in the thread...
    console::write_line("(thread {}) Incrementing value...", thread::current_thread().managed_thread_id());
    for (auto index = 0; index < 300; ++index) {
      ++value;
      thread::sleep(1_ms);
    }
  }};
  
  // Running some_thread.
  some_thread.start();
  
  // Do some work in the main thread...
  console::write_line("(main thread {}) do something...", thread::current_thread().managed_thread_id());
  thread::sleep(100_ms);

  // Wait for the thread to finish.
  some_thread.join();

  console::write_line("Stop : value = {}", value);
}

Using the begin_invoke and end_invoke methods of the delegate class

The delegate class contains begin_invoke and end_invoke methods that allow you to easily execute a delegate in asynchronous mode. These methods use the thread_pool class to distribute asynchronous tasks over a pool of threads managed for you.

#include <xtd/console>

using namespace xtd;

auto main()->int {
  auto value = 0;
  console::write_line("Start : value = {}", value);
  
  auto some_delegate = delegate<void()> {[&] {
    // Do some work in the thread...
    console::write_line("(thread {}) Incrementing value...", xtd::threading::thread::current_thread().managed_thread_id());
    for (auto index = 0; index < 300; ++index) {
      ++value;
      xtd::threading::thread::sleep(1_ms);
    }
  }};
  
  // Running some_thread.
  auto async_result = some_delegate.begin_invoke();
  
  // Do some work in the main thread...
  console::write_line("(main thread {}) do something...", xtd::threading::thread::current_thread().managed_thread_id());
  xtd::threading::thread::sleep(100_ms);

  // Wait for the delegate to finish.
  some_delegate.end_invoke(async_result);

  console::write_line("Stop : value = {}", value);
}

Using the queue_user_work_item methods of the thread_pool class

The queue_user_work_item method of the thread_pool class is used to distribute asynchronous tasks to a thread pool managed on your behalf.

#include <xtd/threading/thread_pool>
#include <xtd/threading/manual_reset_event>
#include <xtd/console>

using namespace xtd;
using namespace xtd::threading;

auto main()->int {
  auto value = 0;
  console::write_line("Start : value = {}", value);
  auto event = manual_reset_event {};
  
  thread_pool::queue_user_work_item([&] {
    // Do some work in the thread...
    console::write_line("(thread {}) Incrementing value...", thread::current_thread().managed_thread_id());
    for (auto index = 0; index < 300; ++index) {
      ++value;
      thread::sleep(1_ms);
    }
    
    // Signal the end of task.
    event.set();
  });
  
  // Do some work in the main thread...
  console::write_line("(main thread {}) do something...", thread::current_thread().managed_thread_id());
  thread::sleep(100_ms);

  // Wait for thread_pool task to finish.
  event.wait_one();

  console::write_line("Stop : value = {}", value);
}

Using the register_wait_for_single_object methods of the thread_pool class

The register_wait_for_single_object method of the thread_pool class is used to distribute asynchronous tasks to a thread pool managed on your behalf.

#include <xtd/threading/thread_pool>
#include <xtd/threading/manual_reset_event>
#include <xtd/console>

using namespace xtd;
using namespace xtd::threading;

auto main()->int {
  auto value = 0;
  console::write_line("Start : value = {}", value);
  auto end_work_event = manual_reset_event {};
  
  thread_pool::register_wait_for_single_object(end_work_event, [&] {
    if (value == 0) console::write_line("(thread {}) Incrementing value...", thread::current_thread().managed_thread_id());
    if (value < 300) ++ value; // Do some work in the thread...
    else end_work_event.set(); // Signal the end of task.
  }, std::any {}, 1, false);
  
  // Do some work in the main thread...
  console::write_line("(main thread {}) do something...", thread::current_thread().managed_thread_id());
  thread::sleep(100_ms);
  
  // Wait for thread_pool task to finish.
  end_work_event.wait_one();
  
  console::write_line("Stop : value = {}", value);
}

Using background_worker component

In a GUI application, it's easiest to use the background_worker component to create a thread. Indeed, the background_worker component is designed so that progress_changed and run_worker_completed events are called automatically in the UI thread. This means that the GUI can be updated directly in the events, without having to use the invoke or begin_invoke and end_invoke methods.

#include <xtd/forms/application>
#include <xtd/forms/background_worker>
#include <xtd/forms/debug_form>

using namespace xtd;
using namespace xtd::diagnostics;
using namespace xtd::forms;

auto main()->int {
  auto debug_form1 = debug_form {};

  auto value = 0;
  debug::write_line("start : value = {}", value);
  
  auto backgound_worker1 = background_worker {};
  backgound_worker1.worker_supports_cancellation(true);
  backgound_worker1.do_work += [&] {
    for (auto index = 0; index < 300; ++index) {
      ++value;
      backgound_worker1.report_progress(value / 3);
      threading::thread::sleep(1_ms);
    }
  };
  backgound_worker1.run_worker_async();

  auto form1 = form {};
  form1.form_closed += [&] {
    backgound_worker1.cancel_async();
  };

  backgound_worker1.run_worker_completed += [&] {
    debug::write_line("stop : value = {}", value);
  };
  
  application::run(form1);
}

Remarks

You can of course use std::thread or any other third-party thread library.

See