So my issue here is simple. I've designed a WinForms application and it works well on my machine (Win7), and in fact other machines, yet when I run the application on a Windows 10 2016 LTSB machine, my background threads do not work as expected - yet some do perform as expected.
Application flow:
Now for some privacy policies/reasons I cannot share the exact things that operate here and how the classes are structured, but here is a rudimentary class structure:
class MainWindow
{
List<Controller> controllers = new List<Controller>();
List<ControllerDisplay> controllerDisplays = new List<ControllerDisplay>();
Queue<string> requests = new Queue<string>();
private void AppLifetimeLoopCallback(object state)
{
while (requests.Count > 0)
{
string request = requests.Dequeue();
string response = controllers[i].ProcessRequest(request);
string anotherResponse = controllerDisplays[i].ProcessResponse(response);
if (!string.NullOrWhiteSpace(anotherResponse))
{
requests.Enqueue(anotherResponse);
}
}
for (int i = 0; i < controllers.Count; i++)
{
requests.Enqueue("STATE?");
}
timer.Change(300, Threading.Timeout.Infinite);
}
}
class Controller
{
public string ProcessRequest(string request)
{
switch (request)
{
case "STATE?":
if (shouldRequest)
{
return "REQ:1234";
}
else if (isProcessing)
{
return "PRQ:1234";
}
else
{
return "IDLE";
}
break;
case "APPROVE":
shouldRequest = false;
isProcessing = true;
thread = new Threading.Thread(new ThreadStart(() =>
{
Threading.Thread.Sleep(300);
isProcessing = false;
return "RQF:1234";
})
{
IsBackground = true,
};
thread.Start();
break;
case "DENY:
shouldRequest = false;
break;
}
}
}
class ControllerDisplay
{
public string ProcessResponse(string response)
{
switch (request.Substring(0, 4))
{
case "REQ:":
thread = new Threading.Thread(new ThreadStart(() =>
{
// perform some checks
if (isValid)
{
return "APPROVE";
}
else
{
return "DENY";
}
})
{
IsBackground = true,
};
thread.Start();
break;
case "RQF:":
thread = new Threading.Thread(new ThreadStart(() =>
{
// finalize and cleanup request bits
return "APPROVE";
})
{
IsBackground = true,
};
thread.Start();
break;
case "PRQ:":
// update UI
break;
}
}
}
Now firstly, I know there seems to be some discrepancy between the millisecond delay in the code and the description of the flow - however note that there is another Thread
in the Controller
which toggles the shouldRequest
value at this minute interval which switches up the response messages to perform the "request" when the device's state is requested.
Secondly I also have registered to the UnhandledException
as well as the ThreadException
events of the application which should log any undesired behaviour that occurred.
Third, note that in MainWindow there is a Threading.Timer
(not in code - I know) that is updating the UI with the current date and time every second.
Now the issue here that I've noticed is that on the Win10LTSB2016 machine, the application stops performing the background operations. Some of the threads must have just died off or something as ie the date and time keeps updating as expected, but one controller will be stuck in request state and another in a request complete state - and no error messages logged / MessageBox
. Note that the machine does not go into any sleep or hibernate state in this period that the threads just stop, and another note is that the memory sockets is 1, not 2 (as I read that this could affect the threads losing communication with each other if they are compartmentalized to different processor groups and your application is not written to handle this).
Closing off: Note that when I perform checks to see if I should ie start the request process thread in the Controller
class so as to not do the same request over and over until state change is detected, I do the following:
lock (checkLock)
{
if (isProcessingRequest)
{
break;
}
else
{
lock (resourceLock)
{
isProcessingRequest = true;
}
}
}
thread = new Threading.Thread(new ThreadStart(() =>
{
lock (resourceLock)
{
// finalize and cleanup request bits
isProcessingRequest = false;
}
return "APPROVE";
})
{
IsBackground = true,
};
thread.Start();
I'm closing this question as it is complete hogwash and I apologize to those for the time they spent reading this.
So the manual locks on the Queue<T>
kept causing a deadlock before, thus they were removed. Now it seemed to resolve the issue at first, but long running tests proved every now and again (what I thought was a Windows issue) a deadlock occurred.
The reason I had thought this was a Windows issue is because someone telling me that this is what they experienced on Windows and it is definitely a Windows issue. Not looking down on anyone, but he does not do threading as he does not know how and the mentioned result was from his attempt to do threading. Lesson learned here.
Thanks guys and/or gals.
EDIT: The issue was resolved and long running tests are looking very promising thus far. To achieve this, I simply changed Queue<T>
to ConcurrentQueue<T>
and a few modifications to code where needed (ie ConcurrentQueue<T>.Clear()
does not exist where Queue<T>.Clear()
does).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.