Gtk.Application.Invoke is not working - c#

I am trying to build an application on MONO using Backgroundworker. My application is working fine when i use the sequential method. Basically my application draws some rectangles the on the drawing area on click of the button.
I am trying to compare the difference in execution time between sequential, using Backgroundworker and others.
I have a problem in using background worker, have a look at the following code,
static void DoWork (object sender, DoWorkEventArgs e)
{
Context ct = (Context)e.Argument;
house.DrawHouse rect = new house.DrawHouse ();
PointD p1, p2, p3, p4;
p1 = new PointD (55, 250);
p2 = new PointD (65, 250);
p3 = new PointD (65, 90);
p4 = new PointD (55, 90);
Gtk.Application.Invoke (delegate {
ct.MoveTo (p1);
ct.LineTo (p2);
ct.LineTo (p3);
ct.LineTo (p4);
ct.LineTo (p1);
ct.ClosePath ();
ct.Color = new Color (0, 0, 0);
ct.FillPreserve ();
ct.Color = new Color (255, 255, 255);
ct.Stroke ();
});
}
}
in the above code worker thread is creating creating the rectangle and giving to the GUI thread to print it. but it is throwing an error in the ct.MoveTo (p1);
Hope to hear from some one soon.

Are you sure you're calling that code in the GUI thread? To find out, you could use this tool.
Also, let me guess: you're running this on Windows, aren't you? I got this impression because AccessViolationExceptions happen more often on MS.NET than on Mono (somehow, the interoperability with the unmanaged world is less strict on Mono).
This has been brought up sometimes in bugs, but not yet fixed. In MS.NET these issues are normally fixed by applying proper calling conventions. An example is this, maybe you're missing some of this? (Or Cairo's binding? be sure to clone gtk-sharp and have a look at the DllImport being called; maybe you can spot a bug there and send a pull request to fix it?)

You are correct. Yes, I am running this on windows. and for the first point of yours, worker thread will start the task and create the rectangle and gives to GUI thread to print it on the screen. (Gtk.Application.Invoke (delegate { }); this will switch to GUI thread)
Have a look at the following code I am doing the same thing but not in perspective of painting but it does some time consuming calculation. The calculation which is time consuming is done by the worker thread and giving the result to GUI thread to print on the UI. This is absolutely working fine for me with out any error.
void DoWork (object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
var watch = Stopwatch.StartNew ();
for (int i = lowerLimit; i <= upperLimit; i++) {
int j = i;
var result = SumRootN (j);
Gtk.Application.Invoke (delegate {
textview15.Buffer.Text += "root " + j.ToString () + " = " + result.ToString () + Environment.NewLine;
});
worker.ReportProgress ((int)(((double)i / (double)upperLimit) * 100));
}
var time = watch.ElapsedMilliseconds;
textview20.Buffer.Text = "Background Worker: \n execution took " + time + " MS to \n complete the execution \n SLOW & RESPONSIVE";
}
But if i do the same thing on for painting it is giving me the error i attached above.
Please correct me if i am wrong
thanks for the reply knocte, I will have look at your response.

Related

How to move mouse cursor using C# using while infinite loop?

I found a solution to move the cursor via this URL in my Windows-Form app.
How to move mouse cursor using C#?
but as i want to run infinitely but with a break so that when i want to stop it, it should stop here is what i'm trying to achieve.
private void btnMove_Click(object sender, EventArgs e)
{
//int i = 0;
while (true)
{
//i++;
Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X - 40, Cursor.Position.Y - 40);
Thread.Sleep(5000);
Cursor.Position = new Point(Cursor.Position.X + 40, Cursor.Position.Y + 40);
}
//Task t = new Task(() =>
//{
//});
//t.Start();
}
It works but freezes my code. I just want to run it, and whenever i want to stop it, it should stop not freeze.
Ultimately, the answer here is: "don't".
Windows forms are based on a message pump. If you have an event-handler from one message (like "click") that loops forever, it will never get around to processing other messages (like "draw"), so: your app is now unresponsive.
Instead of an infinite loop: use a Timer, and move the position in the callback. In this case, a System.Windows.Forms.Timer would be most appropriate.

MOGRE 1.8.1 + WPF (C#) - Back Buffer is not valid when user changes resolution or computer goes to sleep

I'm working with MOGRE 1.8.1 to embed 3D models within a WPF application. I've run into an issue where the application crashes when the user changes resolution or their computer goes to sleep. I believe this is because the render system is trying to draw to a surface that it doesn't have access to anymore.
I'm not exactly sure what to do; I've tried using the dispose method to kill MOGRE and reboot it later (by catching the windows event), but have run into a memory leak. The pause render method included within the MOGRE library does not seem to work either. Does anyone have any ideas on how to circumvent this issue?
Notes
You can find the example I'm running here. Main difference is that I'm using the 1.8.1 .dlls instead -> http://www.codeproject.com/Articles/29190/Blend-the-OGRE-Graphics-Engine-into-your-WPF-proje , but the error is present in both.
OgreImage.cs is where the issues are happening.
Thank you for your help.
This error happen when the device is lost, so you have to add your control in the function RenderFrame()
//WallPaper, CTRL + ALT + DEL, etc
if (this.isDeviceLost)
{
//Recreate the texture render
ReInitRenderTarget();
//Restore device lost
_renderWindow._beginUpdate();
_renderWindow._endUpdate();
_reloadRenderTargetTime = -1;
this.isDeviceLost = false;
}
And this is my ReInitRenderTarget() function
protected void ReInitRenderTarget()
{
DetachRenderTarget(true, false);
DisposeRenderTarget();
_texture = TextureManager.Singleton.CreateManual(
"OgreImageSource RenderTarget",
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
TextureType.TEX_TYPE_2D,
(uint)ViewportSize.Width, (uint)ViewportSize.Height,
0, Mogre.PixelFormat.PF_R8G8B8A8,
(int)TextureUsage.TU_RENDERTARGET);//, null, false, 8);
_renTarget = _texture.GetBuffer().GetRenderTarget();
_reloadRenderTargetTime = 0;
int viewportCount = ViewportDefinitions.Length;
viewports = new Viewport[viewportCount];
for (int i = 0; i < viewportCount; i++)
{
Viewport viewport;
ViewportDefinition vd = ViewportDefinitions[i];
viewport = _renTarget.AddViewport(vd.Camera, zIndexCounter++, vd.Left, vd.Top, vd.Width, vd.Height);
viewport.BackgroundColour = vd.BackgroundColour;
viewports[i] = viewport;
}
var ev = ViewportsChanged;
if (ev != null) ev();
viewportDefinitionsChanged = false;
}

Retrieving data from a database in another thread(Unity3D)

I currently have a code which retrieves data from a database and visualizes it in unity3D. However, everytime it retrieves data in the FixedUpdate() function, it spikes dramatically every 1 second. I'm thinking about using threading to do this but i'm not sure what i'm doing wrong.
This is the Function i call in the thread.
public void retrievefromDB(){
if (timeStep - prevTimeStep > 99) {
timeStep -= 1; //special for this dataset
query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
if (showParent)
query += " AND (Level != 10)";
else
query += " AND (Level == 10)";
query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
dt.Rows.Clear ();
dt = sqlDB.ExecuteQuery (query);
prevTimeStep = timeStep;
}
}
This code lags the scene every 1 second therefore i tried to put it into a thread.
void FixedUpdate()
{
Thread testthread = new Thread(new ThreadStart(retrievefromDB));
testthread.Start ();
}
After putting it in a thread, it keeps crashing the scene after awhile.
Can anyone tell me what I did wrongly? And how do i solve it?
The cause of your original issue is relatively obvious: database access is slow. If you put a database call inline in the FixedUpdate method, you're going to essentially pause your game's movement while the DB access happens (which may well take a second if you have to initialise a connection, for example).
The main issue with your threaded code as posted is that you are starting a new thread every time FixedUpdate is called. That means you're starting 60 new threads per second (by default) which will very quickly cripple your game!
While it's fine to use C# threads in Unity for this sort of work, a better approach would be to create a single thread and allow that to manage the timing, rather than creating a new thread each time the job runs. That would mean creating the thread in Awake() or Start() instead, and then using Thread.Sleep or similar to handle the timing.
Coroutines (as suggested by Mihai in his answer) are great for fixing the timing of events, but they still run on the game thread: if you put your DB code in a coroutine, you'll still see pauses when it runs. If you must run this DB access every second, you need it in a proper thread.
That said, have you considered that the DB access might be unnecessary? A more performant model might be to cache all of the data up front and use it from memory when you need it. (This might not be possible if the data is very dynamic, or if you're running in a memory-restricted environment like a mobile device...)
Whatever you do, you need to stop accessing your database every frame.
You only need the result only once every 60 or frames. You can do this easily by using a variable in which you add up the time passed since last call.
As for multi-threading in Unity, you have three options:
A multi-threading framework for Unity, like
https://www.assetstore.unity3d.com/en/#!/content/7285
C# built-in threading
You need to be careful not to call Unity specific API from the secondary threads you spawn. It's OK to send over data structures like Vector3, Color, etc., but don't call reference objects like GameObjects or Components.
https://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx
Unity Coroutines
Coroutines are Unity's way of simulating multiple threads. It's quite a powerful tool for getting things to run asynchronously in the same thread
http://docs.unity3d.com/Manual/Coroutines.html
using System.Threading.Tasks;
public class Example
{
void StartOnDifferentThread()
{
Task.Factory
.StartNew(() =>
{
FunctionToRun();
})
.ContinueWith(task =>
{
if (task.IsCompleted)
{
// handle result
}
else if (task.IsFaulted)
{
// handle error
}
});
}
void FunctionToRun()
{
// do stuff
}
}
It finally works now. Just had to add these in retrievefromDB()
public void retrievefromDB(){
while(true){
if (timeStep - prevTimeStep > 99) {
timeStep -= 1; //special for this dataset
query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
if (showParent)
query += " AND (Level != 10)";
else
query += " AND (Level == 10)";
query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
dt.Rows.Clear ();
dt = sqlDB.ExecuteQuery (query);
prevTimeStep = timeStep;
}
Thread.Sleep(1);
}
}
And put this into the Start() function
testThread = UnityThreadHelper.CreateThread (() =>
{
UnityThreadHelper.TaskDistributor.Dispatch (() => retrievefromDB ());
});
testThread.Start ();
I'm using the threadhelper from
http://forum.unity3d.com/threads/unity-threading-helper.90128/
so u can go and check it out.
Thanks to everyone who helped! :)

Windows Forms Invoke causing stack overflow?

I'm making a memory reader for a game, and I've got an almost infinite thread running in the background which checks for the players position, and then displays it on a label by using Invoke(). I'll only post the offending function. This gets called on the same thread every 10 ms.
Invoke((MethodInvoker)delegate
{
lblCoords.Text = "Player Coordinates: < " + (int)x + ", " + (int)y + ", " + (int)z + " >";
});
After the code has been running for about 20 minutes, it will crash and throw a StackOverflowException related to this function. Why is it happening and how can I stop it? Obviously I could just stop using a label to show it, though it would be more useful to know why it's happening for future reference.
So this is the thread method, someone mentioned that it's multiple objects getting created at once, I'm going to assume it's this because it is an infinite loop of calling UpdateThread()... Should this have a while loop instead of calling itself?
private void UpdateThread()
{
if (!running) return;
ReadPos();
Thread.Sleep(100);
UpdateThread();
}
private void ReadPos()
{
int pointerAddress = Memory.HexToDec(MemoryOffsets.PlayerPosAddress);
byte[] xVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerX);
byte[] yVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerY);
byte[] zVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerZ);
float x = BitConverter.ToSingle(xVal, 0);
float y = BitConverter.ToSingle(yVal, 0);
float z = BitConverter.ToSingle(zVal, 0);
Invoke((MethodInvoker)delegate
{
lblCoords.Text = "Player Coordinates: < " + (int)x + ", " + (int)y + ", " + (int)z + " >";
});
}
The error the program was showing me pointed at the Invoke method, which is why I thought it was just that causing it. Since it takes about 20 minutes for the exception to occur, I can't get too much information about it.
Should this have a while loop instead of calling itself? Yes, by all means.
Sanly C# will not generate tail calls for this code, meaning it will stack the calls of UpdateThread until the call stack is full. This is causing the StackOverflowException.
So, you would implement something like this:
private void UpdateThread()
{
while (running) //I'm assuming running is a volatile variable
{
ReadPos();
Thread.Sleep(100);
}
}
Note: It is good idea to make running volatile, as it will be set by another thread (I presume).
You could also consider to post the execution to the thread loop or a similar scheduling mechanism instead of having a dedicated thread, on that regard, do your testing to see what works best.
Another thing to consider is to keep your delegate object alive, it will reduce pressure on the garbage collector (since you are currently creating too many short lived objects), but it is not the cause of the StackOverflowException.
Yes, you should use a loop instead.
You are using recursion to make a loop, and as the loop doesn't have a reasonable limit it will fill up the stack with call frames.
Just loop inside the method:
private void UpdateThread()
{
while (running) {
ReadPos();
Thread.Sleep(100);
}
}

System.Threading.Timer: Why is it hating me?

I just started messing around with C#/.NET/mono and stuff, and I'm trying to make a simple song player. For this, I am using winmm.dll (did not find an easy cross-platform solution). The problem is this: I need to update a trackbar along with the song playing. I have two functions, Player.GetLength and Player.GetCurrentPosition, which return the time in miliseconds. If I call them "normally", everything is ok. But I need to call them in a timer, like this:
new System.Threading.Timer((state) =>
{
length = Player.GetLength();
pos = Player.GetCurrentPosition();
trackBar1.Value = (pos / length) * 100;
}, null, 0, 100);
This is GetLength, and GetCurrentPosition is similar:
public static int GetLength()
{
StringBuilder s = new StringBuilder(128);
mciSendString("status Song length", s, s.Capacity, IntPtr.Zero);
return int.Parse(s.ToString());
}
The problem: when one of these two functions gets called, the program just stops, without any warning or exception thrown. Note: I am using .NET
So I was wondering if you can explain to me where I got it wrong :)
One thing I'd note is that System.Threading.Timer fires it's callback in it's own thread. Since you are interacting with the UI, you'd either want to use System.Windows.Forms.Timer (as a component on the form) or invoke back to the UI, as follows:
new System.Threading.Timer((state) =>
{
length = Player.GetLength();
pos = Player.GetCurrentPosition();
trackBar1.Invoke(new Action(()=>trackBar1.Value = (pos / length) * 100));
}, null, 0, 100);
Likewise, I am not sure if the Player class supports/tolerates multiple threads, but if not, there is the possibility that the whole callback needs to be invoked to the UI.

Categories