Real Time updates not working

0
1

I wrote the followng code to update the client every second. This works fine in the window/session that starts the static timer but other windows aren’t auto updated (except when I move the window for example or if I use Application.StartPolling – even though all the windows/sessions have IsWebSocket == true). Tried with Chrome and Edge.

Does anyone have a suggestion?
Thx in advance, Tom

using System;
using Wisej.Web;

namespace Test
{
public partial class WindowTimer : Form
{

private static Wisej.Web.Timer timer = null;
private static int counter = 0;

private bool created = false;
public WindowTimer()
{
InitializeComponent();

if (timer==null)
{
timer = new Timer();
timer.Interval = 1000;
timer.Start();
timer.Tick += timer_TickUpdate;
created = true;
}
timer.Tick += timer_Tick;
this.Text = Application.IsWebSocket.ToString();
Application.StartPolling(10000);
}

private void timer_TickUpdate(object sender, EventArgs e)
{
counter++;
}

private void timer_Tick(object sender, EventArgs e)
{
this.Text = Application.IsWebSocket.ToString() + ” – Counter: ” + counter.ToString();
this.label1.Text = Application.IsWebSocket.ToString() + ” – Counter: ” + counter.ToString();
}
}
}

  • You must to post comments
0
0

@David, the sample you mentioned uses a different timer: System.Timers.Timer.

Statics are single instance objects. When you create a timer object like System.Timers.Timer (it’s a system timer, see MSDN) as a static object it’s available to the application regardless of the scope of the code. This is not a Wisej.NET construct, it’s just statics in any system.

When the thread timer fires an event, it means that the OS calls the handlers attached to the event delegate. To call the handlers the OS creates a thread and simply starts calling all the handlers. If handler1 was attached from session A and handler2 was attached from session B that information is completely lost since the concept of session doesn’t exist in code. So, when the call arrives to handler1 (session A) Wisej.NET allows you to restore the context (session) using any control (controls in Wisej.NET save a reference to the session that owns them) so that the code can execute in the session context.

However, since the call is coming from an OS thread and there is no browser request obviously the server cannot send a response without a request. That’s when you need the websocket connection – to “push” the update out to the browser without the browser having requested it. Application.Update(IWisejComponent): it pushes out to the browser the entire current state differences. Whatever you use as an argument is an IWisejComponent that is used only to retrieve the session. You can also save an reference to Application.Current and use that one.

The example in this issue is different. It used a Wisej.Web.Timer, which is a component that is created on the server AND the browser and it fires the tick event from the browser. The request comes in, and the response goes back. No need to use Application.Update(). Unless, like in the issue, you also attached to the tick event from a different session – the different session doesn’t have a request to respond to because it was coming from the first browser. Which also means that when the first user closes the browser the javascript timer is terminated.

For the shared drawing, you have the same situation. If you create a javascript component it’s in the browser, you cannot share it with another browser. But you can share the set of data use for the drawing. In the sample you mentioned it’s List<Point> this.draw. Make is static, synchronize (lock) access, add a static event and an Application.Update() (actually in this case you don’t need this because the thread timer is already pushing the updates) when adding points and you have a shared drawing system.

See attached.

 

 

 

  • You must to post comments
0
0

Luca, please amend the example Real Time Clock – Wisej.com to showcase Realtime drawing collaboration (whiteboarding) between browser instances.

This will assist with understanding of websocket/statics/crossthread invoke and what Application.Update(this) does.

 


Realtime Clock example changes required:

The multiuser draw cross browser functionality is missing due to the draw variable being a local rather than static (global) across browsers,

Add:

 

private static List<Point> draw = new List<Point>();

Remove  this. prefix from all this.draw  so they are to be just  draw.xxx

for example:

private void label1_TouchEnd(object sender, TouchEventArgs e)
{
this.drawing = false;
draw.Add(Point.Empty);
}

  • You must to post comments
1
1

It’s not bizarre. Static means it’s shared across all threads. The timer is created once (since you created it as a static component). Which means browser1 fires the timer. Then you attached multiple handlers to the same timer instance (because it’s static) therefore the handlers are invoked by the thread that fired the event, which means they execute for other sessions out of context. This is not something related to Wisej.NET. It’s simply the way static instances of anything work.

  • Use Application.Update(this) to push the update to the other browsers; when the first browser is closed the timer will obviously stop; or
  • Don’t use statics; or
  • Use a thread timer instead: https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer?view=net-7.0 (same issue with threads and push updates)

Polling is alternative to websocket.

I tried your sample is all works as expected.

  • Tom Van den Eynde
    Thanks Luca for the clarification. I hoped that updating UI properties (by attaching to the static timer) would be enough to get the updates pushed out to the different browsers. Anyway, it’s good to see that I could use Application.Update or probably even better not use a static timer. To be clear: I love WiseJ. It’s a dream come true!
  • You must to post comments
0
0

Hi Alaa,

Putting the Application.Update in the timer event indeed does the trick but why do I have to specify it? The first application instance (the one which appears when starting the application from Visual Studio updates the form and label without having to call the Update method. The following instances in new browser tabs only work well when calling the Update method. Bizar, isn’t it?? It’s a bit worrying that what you see when starting the application is not what the ‘normal’ users get to see. I’ve attached a solution showing the problem.

Thx,
Tom

Attachment
  • You must to post comments
0
0

Hi Tom,

Would you mind wrapping up a small sample?

You don’t need Polling if WebSocket is enabled, if the update is reflected only when you move a window that means that the context needs updating.

It’s a very simple Application.Update(this) call, where this is the control you’re trying to update!

You can add it to the timer_TickUpdate method:

private void timer_TickUpdate(object sender, EventArgs e)
{
counter++;
Application.Update(this);
}

HTH,
Alaa

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.