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();
}
}
}
@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.
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);
}
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.
Polling is alternative to websocket.
I tried your sample is all works as expected.
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
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
Please login first to submit.