How can i prevent a stackoverflow exception in my software? - c#

I have an audio player that loads a configuration file with a list of files to be played at certain intervals. Like 5 files should be looped between 09:30 and 11:30 - it is an application for libraries where they need the background music.
When im outside of an interval, i loop through all my time intervals (there might be 2 hours before next interval starts) and then if i find that nothing is to be played right now - i sleep for a second and then try again.
I have a problem where i get a stack overflow after around 3-4 hours of checking for these time intervals (often at nights, because the clients are on, but no music should be playing at night).
private void PlayNextFile()
{
Application.DoEvents();
if (currentState == PlayerState.Started)
{
//if we find the next slide then play it
AudioSlide slideToPlay = FindNextSlide();
if(slideToPlay != null)
{
PlaySlide(slideToPlay);
}
else
{
MedianLog.Log.Instance.LogDebug("Did not find a slide to play now, will check again in a second");
System.Threading.Thread.Sleep(1000);
PlayNextFile();
}
}
}
Any idea on how to get around this exception?

You just filling up your stack with not controlled recursive calls.
A while loop would be a better solution.
Something like that should do it correctly:
private async void PlayNextFile()
{
while (true)
{
if (currentState == PlayerState.Started)
{
//if we find the next slide then play it
AudioSlide slideToPlay = FindNextSlide();
if (slideToPlay != null)
{
PlaySlide(slideToPlay);
return;
}
MedianLog.Log.Instance.LogDebug("Did not find a slide to play now, will check again in a second");
await Task.Delay(1000);
}
else
{
return;
}
}
}

Related

Multithreading doesn't work if I start more than 1 other thread

I don't know if this problem is Unity-specific so maybe other C# developers can help me too :)
So I am actually trying to implement my own version of the A* algorithm and to improve performance I want the actual path finding for every seeker to be multi threaded:
It works pretty well until the moment I activate a second seeker:
Like you can see it stops after 15 iterations (varying depending on how many text outputs i call -> I guess the threads are getting killed after a amount of time) in the algorithm and the first started thread gets kind of killed by the following.
I am using the C# ThreadPool class for my thread management but I tried also to use the Thread class. It is the same result.
Implementation of my threading:
public static void RequestPath(PathRequest _request)
{
Debug.Log("Queueing PathRequest...");
ThreadPool.QueueUserWorkItem(instance.StartThreadedPathfinding, _request);
}
The called method:
private void StartThreadedPathfinding(object _stateInfo)
{
PathRequest request = (PathRequest)_stateInfo;
m_pathfinder.FindPath(request, OnPathFound);
}
And FindPath:
public void FindPath(PathRequest _request, Action<PathResult> _callback)
{
Debug.Log("Starting A* Algorithm");
BinaryHeap<Node> openList = new BinaryHeap<Node>(GridSize);
HashSet<Node> closedList = new HashSet<Node>();
Node startNode = _request.Start;
Node targetNode = _request.Target;
bool success = false;
openList.Add(startNode);
while (openList.Count > 0)
{
Debug.Log(Thread.CurrentThread.ManagedThreadId + ": " + Thread.CurrentThread.ThreadState.ToString());
Node currentNode = openList.RemoveFirst();
if (currentNode == targetNode)
{
// TODO: Path found -> _callback
success = true;
Debug.Log("Path found");
_callback(new PathResult(null, success, _request.Callback));
return;
}
closedList.Add(currentNode);
foreach (Node neighbour in currentNode.m_neighbours)
{
if (closedList.Contains(neighbour))
{
continue;
}
int tentativeG = currentNode.m_gCost + GetDistance(currentNode, neighbour);
if (openList.Contains(neighbour) && tentativeG > neighbour.m_gCost)
{
continue;
}
neighbour.m_parent = currentNode;
neighbour.m_gCost = tentativeG;
neighbour.m_hCost = GetDistance(neighbour, targetNode);
if (openList.Contains(neighbour))
{
openList.UpdateItem(neighbour);
}
else
{
openList.Add(neighbour);
}
}
}
// TODO: No path to the target exists -> calculate some path
success = false;
Debug.Log("No existing path");
_callback(new PathResult(null, success, _request.Callback));
return;
}
RequestPath and StartThreadedPathfinding are in a class called PathRequestManager and FindPath is in an other class called Pathfinder.
Another point is that the threads don't just stop because of an error or sth like that but are still somehow running I think because after I started the scene in Unity I have to kill the Unity-process in the taskmanager because sth is stuck (CPU-Load is always about 80% when I have to do that)
Thought about deadlocks but couldn't find any.
I would be glad if someone could help me here and if you need more information about the source code feel free to ask :)
So I found the problem thanks to an answer in the Unity forums:
I was working on the same Grid and therefore on the same Nodes with every thread. When I was updating a Node in the algorithm on one thread while another one was working with the same Node some bad things happend and the result can be seen above in the question.
I solved this by cloning the grid for each thread and working on the grids owned by the threads.

How to detect the end of an AxWindowsMediaPlayer playlist

I currently have a program which plays a set of videos from a playlist then displays a set of images once the videos are done playing. I am currently using the PlayStateChange event to count each time a video is ending but this results in the images displaying at the beginning of the last video and not at the end. I need a way to trigger the images when the playlist is completely done playing. I even tried delaying the code but that causes my display image method to act screwy. Here is a code sample, not that it is really needed to answer my question.
private void player_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (!currSess.playOne)
{
Console.WriteLine(player.playState);
if (e.newState == 8 | e.newState == 9)
{
if (e.newState == 8)
{
currSess.playQueue++;
Console.WriteLine(currSess.playQueue);
}
}
if (currSess.playQueue+1 > player.currentPlaylist.count -1)
{
// await Task.Delay(1000);
displayImgs();
player.PlayStateChange -= foo;
currSess.playQueue = 0;
}
}
}
Fixed by adding another if statement, since if the last video is done playing it will assume the ready state and stop there:
if (currSess.playQueue+1 > player.currentPlaylist.count -1)
{
if (e.newState == 10)
{
// await Task.Delay(1000);
displayImgs();
currSess._timer.start();
Console.WriteLine(currSess._timer);
AllowControls(true);
allowItems();
player.PlayStateChange -= foo;
currSess.playQueue = 0;
}
}

C# why two same thread fire same method at same time?

First of all my question is quite complicated (for me) and I try to explain.
I have a WPF application which is working with NFC tags. Couple days ago this code was worked properly but now somethings messed up.
First I have a method which is reading data from NFC tag like this:
private void NFCCard_OnCardInserted()
{
CheckCard();
}
private bool CheckCard()
{
try
{
lock (_object)
{
NFCCard.Connect(CardReader, SHARE.Shared, PROTOCOL.T0orT1);
APDUPlayer player = new APDUPlayer(ApduListFile, NFCCard);
if (nfcFunction.NFCLogin(player))
{
string TempCompanyID = "";
//--Read data
}
DateTime cartOpenedDate = Convert.ToDateTime(OpenedDate);
if (CartNo == "" || CompanyID.ToString() == "" || Convert.ToInt32(limit) <= 0 || isactive == "False" || cartOpenedDate.ToShortDateString() != DateTime.Today.ToShortDateString() || CartType == "Staff")
{
Dispatcher.BeginInvoke(new Action(delegate
{
ShowCardNo(txtCardNo, "Geçersiz Kart!");
}));
}
else
{
//-- Some internal code
}
}
}
catch (Exception exc)
{
StationSession.WriteLog("write log bla bla", exc);
}
}
Now is the funny thing when I check the threads windows of VS two same thread try to run NFCCard_OnCardInserted() method at same time.
For this reason I put lock state but the problem is this method firing two times. And its make big trouble for me because the card transaction time is being double right now (almost 3 second for some transaction. I cannot explain to people you will wait with cart at cart reader like this :/ ). By the way I check whole page for this method reference, just this code should use this method.
NFCCard.OnCardInserted += new CardInsertedEventHandler(NFCCard_OnCardInserted);
So how can I fix this problem without workaround. Because I have several page and method which is using NFC cart thread. I need to find clear way for this problem. Thanks.

Different functions different delays c#

I'm making a simple c# game similar to snake, and I have two moving aspects. I have a method to move both of them, however I want them to both move at different speeds. Here's a cut down version of the method I have now.
private async void mover()
{
while (GlobalVar.Status == "alive")
{
if (GlobalVar.Direction == "up")
{
try { moveupp(GlobalVar.Row, GlobalVar.Column, "player"); }
catch (System.IndexOutOfRangeException) { died(); }
}
if (GlobalVar.OppDirection == "up")
{
try { moveupp(GlobalVar.Row, GlobalVar.Column, "opp1"); }
catch (System.IndexOutOfRangeException) { died(); }
}
await Task.Delay(500);
}
}
Here, in the first IF statement, my character (player) is moving up, and in the second IF statement, the opponent (opp1) is moving up. These are working in sync with a 500 millisecond delay in between with the delay "await Task.Delay(500);".
My question is, is there anyway they can both run together, with different delays in between? So the opp1 can move faster than the player?
Many thanks in advance!
I would use two different timers instead of delaying tasks. Also I would not use exceptions to control program flow:
private PlayerTimer_Tick(object sender, EventArgs e)
{
if (GlobalVar.Status != "alive")
return; // you can also stop timer in this case
if (GlobalVar.Direction == "up")
{
if (GlobalVar.Column == 0)
died();
else
moveupp(GlobalVar.Row, GlobalVar.Column, "player");
}
}
Also create timer for opp1 and set different intervals for these timers - 500 for player and another value for opp1.

GTK+ widgets/windows being (randomly) corrupted, with what seems to be timers

I have recently implemented a scrolling text across an area of limited screen estate using a timers repeating every 100ms, and some simple string appending.
However, after this very implementation, I have come to realise that my GUI is getting randomly bugged/corrupted after a certain while. That is to say that some widgets/windows become completely white, and eventually the entire GUI turns white and unclickable.
What is weird is that there is no error debug output at all.
Having said that, I am using Mono with GTK-Sharp for the application. Does anyone have an idea or a possible clue how and why this is happening?
If not, how can I further debug this properly?
Thanks, really appreciate it.
PS: Sometimes, it takes up to 1.5 hours for the thing to start corrupting, it has random timeframes for it to start happening.
This is my the code implemented that caused this issue:
void ScrollSyncTo(object sender, System.Timers.ElapsedEventArgs e)
{
//initial check if it fits nicely alr
if (sync_to_full_txt.Length <= sync_to_max_char)
{
sync_to_timer.Stop();
return;
}
//check for pause
if (sync_to_pause >= 0)
{
sync_to_pause--;
return;
}
//check direction
int temp_psn;
string temp_str;
if (sync_to_direction)
{
temp_psn = sync_to_posn + 1;
if (sync_to_full_txt.Substring(temp_psn).Length < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = false;
sync_to_posn = sync_to_full_txt.Length - 1;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn, sync_to_max_char);
}
}
else
{
temp_psn = sync_to_posn - 1;
if (temp_psn + 1 < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = true;
sync_to_posn = 0;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn - sync_to_max_char + 1, sync_to_max_char);
}
}
//lets move it
sync_to.Text = temp_str;
sync_to_posn = temp_psn;
}
To program in GTK with multiple threads, you have to do a couple things to make your program thread-safe. Here is short explanation using C.
I'm more familiar with GTK in C, but I'm assuming it works the same in GTK#. So you have to call GLib.Thread.Init() and Gdk.Threads.Init() at the beginning of your program, bracket your call to Application.Run() with Gdk.Threads.Enter() and Gdk.Threads.Leave(), and also make sure any GTK and GDK calls in background threads (not GTK signal handlers) are between Gdk.Threads.Enter() and Gdk.Threads.Leave().
System.Timers.Timer callbacks come from a threadpool thread, but GTK objects can only safely be accessed from the GTK thread. I would suggest using GLib.Timeout, which runs on the GTK thread.

Categories

Resources