Hello,
I have an app with a UI thread and network thread. The network thread communicates with a server and uses Invoke and BeginInvoke to call functions in the UI thread, to update the UI. I’ve been testing this app with Wisej for a few weeks, but I can’t seem to get anything that uses Invoke or BeginInvoke to work. The functions appear to execute, but the UI is never updated.
Is this supposed to work, or is it a known problem? If it’s a known problem, will it be fixed in tomorrow’s release, or a subsequent release?
Thanks,
David Muse
Hi David,
Thank you for the test case. The issue with your code is that the thread is out of context. There is no way for a thread on the server to know the session that started it unless you pass it to the thread start method, etc.
That’s why we have Application.RunInContext(), Application.StartTask, and Application.Update(). See https://docs.wisej.com/docs/concepts/background-tasks.
When adding Application.Update(this) at the end of your thread method the update works, but it has nothing to update since the code before (adding the panel) couldn’t flag the component as needing an update since the code before the update is running out of context. It can still access all the components, since Wisej components can run in the thread, but the session is not reachable.
To make it short :), this is how to fix your test code: two different ways:
Application.Update(this, () => { Panel p2 = new Panel(); p2.BackColor = Color.Green; p2.Location = new Point(50, 50); Controls.Add(p2); });
Also, as I mentioned before, you don’t need to use this.Invoke((Action)delegate(){}). It doesn’t do anything with Wisej, it simply calls the delegate.
I also noticed that your Web.config is coming from a mistaken template that we have distributed during the beta. Please change the json handler in Web.config to:
<add name=”json” verb=”*” path=”*.json” type=”System.Web.HttpForbiddenHandler” />
The handler is not necessary at all. However, we thought that some apps may store sensitive information in the configuration json and this setting prevents someone from downloading the json. The mistaken handler we had did exactly the opposite.
HTH
Best,
Luca
I’ve attached a fairly simple example that illustrates the problem that I am having. It includes nearly identical Wisej and Winforms projects.
The program creates a Form, then adds Red, Green, and Blue panel to it. The Green panel is added using a thread with Invoke.
The Winforms version works as expected, but the Wisej version doesn’t display the Green panel.
I tried replacing Invoke() with BeginInvoke(). I also tried calling the invoked code directly. I also tried adding Application.Update(this); after the Controls.Add() call, in all three cases. No matter what, I always get the same result.
I’m sure I’m doing something wrong, but it’s not clear what. I’d appreciate any insight.
Thanks,
Dave
Hi David,
In addition to Nic’s reply, I’d like to add that threads don’t really matter in Wisej and you don’t need Invoke() to make cross thread calls. You can simply call any method on any component from any thread.
We have re-implemented Invoke and BeginInvoke to provide similar functionality as WinForms but within a server environment:
private void button1_Click(object sender, EventArgs e) { this.button1.Text = "1"; this.button1.BeginInvoke((Action)delegate() { this.button1.Text += "2"; }); this.button1.Text += "3"; }
The button’s text will be “132” and *not* “123”, because the code in BeginInvoke() is executed *after* everything else is done in Wisej and right before returning to the client. So there is no timer or message overhead, it’s all clean and straightforward.
If you’d like to upload a simple test case showing what you’d like to achieve we can help further.
HTH
Best,
Luca
Hi David,
I have a lot of background threads in my application and it took quite a long time for me to work out how to get it all going (with the help of Luca). Basically the “magic” is to wrap any updates on any wisej control on the background thread in an Application.update task – as I understand it this ensures that the wisej framework will then push these updates to the browser assuming you are running in websocket mode (which you won’t be if you are using VS on windows 7).
i.e.
Application.Update(this, () =>
{
//Do something that updates my UI
}
Note: this in my snippet above is any wisej control.
For non-web socket connections you also need to have a wisej.timer on the form attached to an event on the server, even if that event is empty, to ensure that wisej processes your other updates.
HTH
Nic