LogoLogo
HomeNewsSupportVideos
  • Introduction
  • Getting Started
  • What's new in 4.0
    • Known Issues
    • .NET Core Designer
    • Managed Graphics
    • Fluent Markup
    • Markdown Support
    • Upgrade from 3.x
  • Releases
    • What's new in 4.0
    • What's new in 3.5
    • What's new in 3.2
      • View Builder
      • Validation Rules
      • Enhanced Font Support
      • Design-Time Debug
    • What's new in 3.1
    • What's new in 3.0
      • FAQs
      • Update Existing Projects
      • Multi Targeting
      • Visual Studio Designer
      • Referencing Assemblies
      • Docker Support
      • Troubleshooting
      • Deployment
    • What's new in 2.5
    • What's new in 2.2
    • What's new in 2.1
    • What's new in 2.0
    • Upgrade from 1.x
  • Getting Started
    • New Project
    • Templates
    • Troubleshooting
    • License Activation
    • FAQ
    • API
    • Hybrid
    • Deployment
    • Theme Builder
  • Concepts
    • Startup
    • Configuration
    • Load Balancing
    • Designer
    • Layouts
    • Client Profiles
    • Tab Order
    • Compression
    • Embedded Resources
    • Modal Workflow
    • Localization
    • RightToLeft
    • Background Tasks
    • Real Time Web Applications
    • JavaScript
    • JavaScript Object Model
    • Security
    • Synchronization
    • Session Management
    • Theming
    • Dependency Injection
    • Application Switches
    • Visual Studio Code
  • Controls & Components
    • General
      • Application
      • AutoSizing
      • AutoScroll
      • AutoScaling
      • Accessibility
      • Colors & Fonts
      • Embedded Tools
      • Events
      • Touch Events
      • Images
      • Labels
      • ToolTips
      • Data Binding
      • Common Properties
      • Custom Painting
      • Move & Resize
      • Drag & Drop
      • Validation
      • User Data
      • Responsive Properties
      • VB.NET Extensions
    • Common Dialogs
      • FolderBrowserDialog
      • ColorDialog
      • OpenFileDialog
      • SaveFileDialog
    • Editors
      • TextBox
        • TagTextBox
        • MaskedTextBox
        • TypedTextBox
      • DateTimePicker
      • MonthCalendar
      • TimeUpDown
      • DomainUpDown
      • NumericUpDown
      • TrackBar
    • Buttons
      • Button
      • SplitButton
      • CheckBox
      • RadioButton
    • Containers
      • Page
      • Form
      • Desktop
      • Panel
      • FlexLayoutPanel
      • FlowLayoutPanel
      • TableLayoutPanel
      • GroupBox
      • Accordion
      • TabControl
      • UserPopup
      • UserControl
      • ToolBar
      • StatusBar
      • SplitContainer
      • SlideBar
    • Lists & Grids
      • ComboBox
        • UserComboBox
        • TreeViewComboBox
        • ListViewComboBox
      • ListBox
        • CheckedListBox
      • TreeView
      • ListView
      • DataGridView
        • Column
        • TextBoxColumn
        • ButtonColumn
        • LinkColumn
        • ImageColumn
        • MaskedTextBoxColumn
        • DateTimePickerColumn
        • NumericUpDownColumn
        • CheckBoxColumn
        • ComboBoxColumn
      • DataRepeater
      • PropertyGrid
    • Extenders
      • Animation
      • ToolTip
      • ErrorProvider
      • Rotation
      • StyleSheet
      • JavaScript
    • Media
      • Audio
      • Video
      • FlashPlayer
    • Content
      • Label
      • LinkLabel
      • PictureBox
      • ScrollBars
      • Upload
      • AspNetPanel
      • ImageList
      • PdfViewer
      • ProgressBar
      • Spacer
      • Widget
      • WebBrowser
      • IFramePanel
      • HtmlPanel
      • Canvas
      • Shape
      • Line
    • Menus
      • MainMenu
      • MenuBar
      • MenuItem
      • LinkMenuItem
      • ContextMenu
    • Notifications
      • AlertBox
      • MessageBox
      • Toast
    • Other Components
      • Timer
      • BindingSource
      • BindingNavigator
      • DataSet
      • EventLog
      • MessageQueue
      • PerformanceCounter
Powered by GitBook
On this page
  • What is a Background Task?
  • Update the UI
  • Systems Without WebSocket
  • Background Task with Multiple Users

Was this helpful?

Export as PDF
  1. Concepts

Background Tasks

PreviousRightToLeftNextReal Time Web Applications

Last updated 3 months ago

Was this helpful?

Background Tasks are one of the most important features of Wisej.NET. No other Web development system allows developers to launch background tasks (threads) on the server and update the client asynchronously with the same level of simplicity and robustness.

What is a Background Task?

A Background Task runs on the server in the background after the client request has completed, allowing users to continue working while the task executes.

Background tasks operate independently from the session and user that initiated them. They run as separate threads without any session knowledge. You can even start separate threads when an application first loads, before any session or user request exists.

To run code when an application first loads, create a static constructor on any class. The most appropriate would be Program.cs or the first page or window created for new sessions.

What can I do in a Background Task?

Anything - connect to other servers, query databases, use the file system, access remote services, etc.

How do I terminate a Background Task?

Simply return from the call. A background task (like any thread) starts by calling your start method and runs until you exit it. Typically it's a loop that checks conditions and uses Thread.Sleep(ms) periodically, exiting when complete.

Update the UI

Wisej.NET provides a straightforward way to launch a Background Task bound to a specific session, allowing code to interact with the user's UI in real-time.

void button1_Click(EventArgs e)
{
  Application.StartTask(() =>
  {
    // Change the text of button 1 from 1 to 10 in the background.
    for (int i = 0; i < 10; i++)
    {
      this.button1.Text = i.ToString();

      // We are running out-of-bound and we need to push the updates
      // to the client using Application.Update(). It can be called at any time
      // and interval. It simply flushes the changed back to the client.
      Application.Update(this);

      Thread.Sleep(1000);
    }
  });
}
Private Sub button1_Click(e As EventArgs)

  Application.StartTask(Sub()

    ' Change the text of button 1 from 1 to 10 in the background.'
    For i = 0 To 10
      Me.button1.Text = i.ToString()

      ' We are running out-of-bound and we need to push the updates'
      ' to the client using Application.Update(). It can be called at any time'
      ' and interval. It simply flushes the changed back to the client.'
      Application.Update(this)

      Thread.Sleep(1000)
    Next
  End Sub)

End Sub

The example above updates the specific button1 in the session that started the task because the thread is started using Application.StartTask().

Application.StartTask() starts a new thread and updates the context to match the calling session. If using Thread.Start() instead, the thread method couldn't access session objects unless wrapped in Application.RunInContext().

When code runs in context (either in-bound or out-of-bound for background tasks), you can call Application.Update() anytime to push UI updates to the client.

Systems Without WebSocket

Older clients or servers may not support WebSocket connections, preventing out-of-bound UI updates from background tasks reaching the client browser.

Wisej.NET provides alternative client updates using Application.StartPolling(milliseconds) and Application.EndPolling() to enable periodic server polling. These methods are ignored when using WebSocket connections.

// this has no effect when the client and server are connected using WebSocket.
Application.StartPolling(1000);

Application.StartTask(() => {

    for (int i = 0; i < 100; i++) {
        this.label1.Text = "Counting..." + i;
        Thread.Sleep(1000);
    }

    // this has no effect when the client and server are NOT connected using WebSocket.
    Application.Update(this);

    // this has no effect when the client and server are connected using WebSocket.
    Application.EndPolling();
});
' this has no effect when the client and server are connected using WebSocket.'
Application.StartPolling(1000)

Application.StartTask(Sub()

    For i = 0 To 100
        Me.label1.Text = "Counting..." + i
        Thread.Sleep(1000)        
    Next

    ' this has no effect when the client and server are NOT connected using WebSocket.'
    Application.Update(this)

    ' this has no effect when the client and server are connected using WebSocket.'
    Application.EndPolling()
    
End Sub)

Check with Microsoft and other technology providers to determine which platforms support WebSocket connections

Background Task with Multiple Users

Since Background Tasks aren't bound to specific sessions, they can perform global tasks serving multiple users simultaneously. While the previous example showed a single-session task, we can create session-independent tasks.

Examples include chat servers, stock market watchers, or any task periodically checking resources. The recommended approach is firing events from the service (background task) and letting user sessions subscribe to these events.

Below is a simplified service firing events every second with a subscribing client.

static class Program
{
  static Program()
  {
    // Start the service.
    BackgroundService.Start();
   }
   ...
}

public static class BackgroundService
{
  private static Thread _thread;
  private static bool _stop = false;

  public static event BackgroundServiceEventHandler Message;

  public static void Start()
  {
    if (_thread == null)
      _thread = new Thread(ThreadStart);

    _stop = false;
    _thread.Start();
  }

  private static void ThreadStart()
  {
    var i = 0;
    while (!_stop)
    {
      Thread.Sleep(1000);

      i++;
      if (Message != null)
        Message(null, new BackgroundServiceEventArgs("Hello #" + i));
    }
  }

  public static void Stop()
  {
    _stop = true;
  }
}
Module Program

  Sub New()
    ' Start the service.'
    BackgroundService.Start()
  End Sub
  ...
End Mdule

Module BackgroundService

  Private _thread As Thread
  Private _stop As Boolean

  Public Event Message As BackgroundServiceEventHandler

  public Sub Start()
  
    If _thread = null Then
      _thread = new Thread(ThreadStart)
    End If
    
    _stop = false
    _thread.Start()
  End Sub

  Private Sub ThreadStart()

    Dim i as Int32
    While Not _stop
    
      Thread.Sleep(1000)

      i++
      If Not Message Is Nothing Then
        Message(Nothing, New BackgroundServiceEventArgs("Hello #" + i))
      End If
      
    End While
  End Sub

  Public Sub Stop()
    _stop = true
  End Sub
  
End Module

Handling Events from the Background Service

private void button1_Click(object sender, EventArgs e)
{
  // Any number of clients can attach to the event from the Background service.
  if (_subscribed)
    BackgroundService.Message -= BackgroundService_Message;
  else
    BackgroundService.Message += BackgroundService_Message;

  _subscribed = !_subscribed;
  this.button1.Text = _subscribed ? "Unsubscribe" : "Subscribe";
}
private bool _subscribed;

// The event handler is called by the Background service thread, so the thread
// doesn't have any knowledge of the session, but "this" refers to this specific
// object, which allows Wisej.NET to restore the context while executing the code below.

private void BackgroundService_Message(object sender, BackgroundServiceEventArgs e)
{
  // Application.Update() can optionally call a code block in context before updating the UI.
  Application.Update(this, () =>
  {
    this.label1.Text = e.Message;
  });
}
Private Sub button1_Click(sender As Object, e As EventArgs)

  ' Any number of clients can attach to the event from the Background service.'
  If _subscribed Then
    RemoveHander BackgroundService.Message, AddressOf BackgroundService_Message
  Else
    AddHandler BackgroundService.Message, AddressOf BackgroundService_Message
  End If

  _subscribed = Not _subscribed
  Me.button1.Text = If (_subscribed, "Unsubscribe", "Subscribe")
End Sub

Private _subscribed as Boolean

' The event handler is called by the Background service thread, so the thread'
' does not have any knowledge of the session, but "this" refers to this specific'
' object, which allows Wisej.NET to restore the context while executing the code below.'

Private Sub BackgroundService_Message(sender As Object, e As BackgroundServiceEventArgs)

  ' Application.Update() can optionally call a code block in context before updating the UI.'
  Application.Update(Me, Sub()
    Me.label1.Text = e.Message
  End Sub)
  
End Sub

The power and simplicity of background tasks in Web applications through the Wisej.NET framework allows handling the browser from the server as if it were a screen directly connected to the server.

If the client or server doesn't support WebSocket, Application.Update() has no effect since the connection doesn't exist. Wisej.NET provides alternative client updates through automatic polling. See and pollingInterval in .

Real Time Web Applications
Configuration
354KB
Wisej.BackgroundTasks.zip
archive
Download Wisej.BackgroundTasks.zip
13KB
Wisej.BackgroundService.zip
archive
Download Wisej.BackgroundService.zip