Click or drag to resize

Background Tasks

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

Downloads-32Download Background Tasks Example

What is a Background Task?

In short, it's exactly what the name says. It's a task running on the server in the background, which means that the client request has been completed and the user is doing other things while the task is still running.

Background tasks are completely separated from the session and the user that started them. They are simply threads running on their own without any knowledge of the session that started them. In fact, you can start separate threads when an application is loaded the first time without any session or user request.

Note Note

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

What can I do in a Background Task?

Anything. You can connect to other servers, query the database, use the file system, remote services, etc...

How do I terminate a Background Task?

It's simple, just return from the call. A background task (like any thread) starts by calling your start method. The method will run until you exit it. Typically it's a loop that checks certain conditions and goes to sleep periodically (using Thread.Sleep(ms)) and exits when it's done.

Update the UI

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

Background Task updating the UI
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);
    }
  });
}

The example above is able to update the specific button1 in the specific session that started the task by clicking button one because the thread is started using Application.StartTask().

Application.StartTask() starts a new thread and then updates the context to match the calling session. If you started the thread using Thread.Start() instead, the code in the thread method wouldn't be able to access the objects in the session unless you wrapped the call in Application.RunInContext().

When your code is running in context (either in-bound, or out-of bound for background tasks) you can call Application.Update() at any time to push the UI updates to the client.

Caution note Caution

If the client or the server don't support WebSocket, calling Application.Update() doesn't have any effect since the connection is simply not there. Wisej provides an alternative method to update the client through automatic polling. See Real Time Web Applications and pollingInterval in Configuration.

Older Clients/Servers Without WebSocket

Older clients or servers may not support WebSocket connections, therefore out-of-bound UI updates from a background task cannot be pushed to the client browser.

Wisej provides an alternative method to update the clients, you can use the Application.StartPolling(milliseconds) and Application.EndPolling() methods to make the client periodically poll the server for updates. These methods are ignored when the client is connected using WebSocket.

Updating without WebSocket
// this has not 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 not effect when the client and server are NOT connected using WebSocket.
Application.Update(this);

// this has not effect when the client and server are connected using WebSocket.
Application.EndPolling();
});
Note Note

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

Background Task with Multiple Users

Since a Background Task is not bound to a specific session, it can perform global tasks that can serve many users at the same time. The example above shows a task serving a single session (update the text in the button for a specific user), but we can easily create a task that is not bound to any session.

Examples could be a chat server, a stock market watcher, or any other task that periodically checks a resource of any kind. The best way to create such a service would be to fire events from the service (the background task) and let user sessions subscribe to the events.

The example below shows a simplified service that fires an event every second and a client that subscribers to the event.

Downloads-32Download BackgroundService Tutorial

Starting a Background Service
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;
  }
}
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 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;
  });
}

It's hard to overestimate the power and simplicity of background tasks in Web applications and the simplicity provided by the Wisej framework. You can handle the browser from the server as if it was a "screen" directly connected to the server...

See Also

Other Resources