I am creating a C# console application of showroom.
I want something like that:
{
customer comes and places an order.
when order completse then I want the main page back.
where customer can re order or re use this application.
}
Actually I want to re run application during runtime.
Is there any specific function or syntax in C#?
I dont know any function that reruns your program. But I also think that its not the best idea to just rerun the program if you want to get back to the programs starting point.
Here is a sample implementation of the loop:
class Program
{
private bool _running = true;
static void Main(string[] args)
{
Program program = new Program();
while (program._running)
{
PlaceOrders();
...
if (exitCondition)
{
program._running = false;
}
}
}
}
You should store all your orders in a database or something similar. At the start of the application you can then load all the orders and give the user the possibility of changing orders, ...
Related
Background info
I am writing an integration test that spawns a child process (c# console app). The test is counting some rows in the database after the process is spun up and after the process is closed. The process is closed via process.Kill()
When the process is killed in this manner, it doesn't hit the Stop method within the process. I need to call this stop method to stop threads and remove entries from the database in order for the test to pass.
Original Code
The console app process that I am spawning in my test:
static void Main(string[] args)
{
TaskManager tm = new TaskManagerProcess();
if (Environment.UserInteractive ||
(args.EmptyForNull().Any(a => a.Equals("-RunInteractive", StringComparison.OrdinalIgnoreCase) || a.Equals("/RunInteractive"))))
{
tm.ConsoleStart(args);
Console.WriteLine("Press [Enter] to shut down, any other key to mark");
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
break;
Console.WriteLine("========================================================");
Console.Out.Flush();
}
Console.WriteLine("Shutting down...");
tm.ConsoleStop();
}
else
{
ServiceBase.Run(tm);
}
}
}
The test code:
//count before starting child proc
int preCount;
//count after process is spun up
int runningsCount;
//count after stopped
int postCount;
//Get an initial count of the logged in modules before svc host is started
user = ApiMethod.GetLoggedInUsers().Where(x => x.RecId == userRecID).FirstOrDefault();
preCount = user.LoggedInModules.Count;
Process proc = Helper.StartProcess(ConnectionBundle);
//Give process time to spin up leaders and workers
await Task.Delay(TimeSpan.FromSeconds(30));
//Get a count of modules after process is spun up
user = ApiMethod.GetLoggedInUsers().Where(x => x.RecId == userRecID).FirstOrDefault();
runningCount = user.LoggedInModules.Count;
//Write a line terminator to the child svc host process -
//this allows it to shutdown normally
Helper.ProcessInput.WriteLine();
Helper.ProcessInput.Close();
Helper.KillProcess(proc);
await Task.Delay(TimeSpan.FromSeconds(5));
//Get count of logged in modules after process is closed
user = ApiMethod.GetLoggedInUsers().Where(x => x.RecId == userRecID).FirstOrDefault();
postCount = user.LoggedInModules.Count;
Helper is a static class that sets up the process start info(including args) and starts the process. In helper I've redirected the StandardInput and added a property ProcessInput which is set to the StandardInput of the created process.
My goal is to send input of "Enter" from the test to the spawned process so that it will break from the loop and call tm.ConsoleStop()
TaskManagerProcess is a private custom class that controls the process. It does not inherit from System.Diagnostics.Process. As an alternate approach, my test could interact with TaskManagerProcess directly. However, I can't make TaskManagerProcess public and I need to run TaskManagerProcess in its own AppDomain because calling ConsoleStop is disposing objects in the API that I need to finish the test.
Things I've Tried
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(CloseProcDelgate handler, bool add);
I tried adding a call to Kernel32.SetConsoleCtrlHandler (and the necessary delegate) to call ConsoleStop when the process is exited. This doesn't seem to work when the process is killed via process.Kill()
With the original process code, I noticed an exception when I wrote to the StandardInput. The exception message told me to use Console.Read instead of Console.ReadKey(). This actually works intermittently! I can sometimes get a breakpoint on int cKey = Console.Read() (with debugger attached to child process) but other times it doesn't hit the breakpoint.
while (true)
{
//Changing this to Console.Read instead of Console.ReadKey
//Allows us to send redirected input to process?
int cKey = Console.Read();
if ((ConsoleKey)cKey == ConsoleKey.Enter)
break;
Console.WriteLine("========================================================");
Console.Out.Flush();
}
Finally, I tried interacting with TaskManagerProcess directly. I made the private class internal, and marked the internals visible to my test assembly. I cannot make the class public.
When I go this route, calling tm.ConsoleStop() blows away some objects in my API so I can't check the count after this method is called. For this reason, I thought I would create a new AppDomain and call AppDomain.CreateInstanceAndUnwrap() on the TaskManagerProcess class. However, I get an exception here, I believe its due to the the fact that the class is internal.
I am really stuck at this point! Any help is appreciated and thanks for taking the time to read this!
Edit
I created a demo project here
that shows what I am trying to do and has both approaches in the Test method.
Initially I thought I couldn't call AppDomain.CreateInstanceAndUnwrap() because the TaskManagerProcess class was internal. However, after playing with my demo project, I think I just can't load the assembly.
I'm guessing here, but I believe your TaskManagerProcess is a service application. If it is not, please ignore this. If it is, be advised of including details like this in your question. Debugging service applications can be complicated, believe me, I've been there. But before proceed, more advise.
Test the methods in your modules, no whole running programs, as Michael Randall just said.
Unless absolutely necessary, don't do tests against a database. Mock whatever you need to test your code.
You should go back to your alternate approach of interact with TaskManagerProcess directly. From the code of your console app, the only working method I see called is tm.ConsoleStart(args), the rest inside the loop is console writing and reading. So you can't change the acces level of that class, again, I've been there. What I have done in the past to overcome this is to use conditional compilation to create a kind of public facade in my private or internal modules.
Suppose you have:
internal class TaskManagerContainer
{
private class TaskManagerProcess
{
internal void Start()
{
// stuff
}
private void DoSomething(int arg)
{
// more stuff
}
}
}
Change it like this:
#define TEST
// Symbol TEST can also be defined using the GUI of your IDE or compiler /define option
internal class TaskManagerContainer
{
//
#if TEST
public class TaskManagerProcess
#else
private class TaskManagerProcess
#endif
{
internal void Start()
{
// stuff
}
private void DoSomething(int arg)
{
// more stuff
}
#region Methods Facade for Testing
#if TEST
public void Start_Test()
{
Start();
}
private void DoSomething_Test(int arg)
{
DoSomething(arg);
}
#endif
#endregion
}
}
I really hope it will help you making the methods visible to the test assembly and it won't blow objects in you API.
I think I got it with a brute force approach.
while (!testProcess.HasExited)
{
testProcess.StandardInput.WriteLine();
}
Thanks everyone for the input!
Hey people when I execute this small code the console doesn't display anything
Im beginner in c# but my code seems correct :(
class Program
{
static int Factorial(int n)
{
if (n==0)
{
return 1; //base case
}
else
{
return n * Factorial(n - 1); //recursive case
}
}
static void Main(string[] args)
{
Factorial(5);
}
}
The problem is that you are not asking your program to write anything. The program is not supposed to write anything by itself, except if you are asking it to do so. To display an information, you need to use Console.WriteLine() or any other function that can write information in your standard output stream.
You seem to misunderstand the purpose of the return statement. The goal of return is just to tell to the function which value it is supposed to return to the function who called it. The calling function then can store this value and treat it for additional purposes, such as printing it like you wanted to do there.
static void Main(string[] args)
{
int factorialValue = Factorial(5); // factorialValue contains
// the returned value of Factorial(5)
Console.WriteLine(factorialValue);
}
Because you haven't write anything to the console, If you want to display something in the console you have to write to the console for that you can use the WriteLine() method of the Console class. Which is an overloaded method you can check the possible overloading options here with MSDN. So the changes in your code would be like the following:
static void Main(string[] args)
{
int inputNum = 5;
Console.WriteLine("Factorial of {0} is {1}",inputNum,Factorial(inputNum));
}
I have a user control that displays information from the database. This user control has to update these information constantly(let's say every 5 seconds). A few instances of this user control is generated programmatically during run time in a single page. In the code behind of this user control I added a code that sends a query to the database to get the needed information (which means every single instance of the user control is doing this). But this seems to slow down the processing of queries so I am making a static class that will do the querying and store the information in its variables and let the instances of my user control access those variables. Now I need this static class to do queries every 5 seconds to update its variables. I tried using a new thread to do this but the variables don't seem to be updated since I always get a NullReferenceException whenever I access them from a different class.
Here's my static class:
public static class SessionManager
{
public static volatile List<int> activeSessionsPCIDs;
public static volatile List<int> sessionsThatChangedStatus;
public static volatile List<SessionObject> allSessions;
public static void Initialize() {
Thread t = new Thread(SetProperties);
t.Start();
}
public static void SetProperties() {
SessionDataAccess sd = new SessionDataAccess();
while (true) {
allSessions = sd.GetAllSessions();
activeSessionsPCIDs = new List<int>();
sessionsThatChangedStatus = new List<int>();
foreach (SessionObject session in allSessions) {
if (session.status == 1) { //if session is active
activeSessionsPCIDs.Add(session.pcid);
}
if (session.status != session.prevStat) { //if current status doesn't match the previous status
sessionsThatChangedStatus.Add(session.pcid);
}
}
Thread.Sleep(5000);
}
}
And this is how I am trying to access the variables in my static class:
protected void Page_Load(object sender, EventArgs e)
{
SessionManager.Initialize();
loadSessions();
}
private void loadSessions()
{ // refresh the current_sessions table
List<int> pcIds = pcl.GetPCIds(); //get the ids of all computers
foreach (SessionObject s in SessionManager.allSessions)
{
SessionInfo sesInf = (SessionInfo)LoadControl("~/UserControls/SessionInfo.ascx");
sesInf.session = s;
pnlMonitoring.Controls.Add(sesInf);
}
}
Any help, please? Thanks
Multiple threads problem
You have one thread that gets created for each and every call to SessionManager.Initialize.
That happens more than once in the lifetime of the process.
IIS recycles your app at some point, after a period of time should you have absolutely no requests.
Until that happens, all your created threads continue to run.
After the first PageLoad you will have one thread which updates stuff every 5 seconds.
If you refresh the page again you'll have two threads, possibly with different offsets in time but each of which, doing the same thing at 5 second intervals.
You should atomically check to see if your background thread is started already. You need at least an extra bool static field and a object static field which you should use like a Monitor (using the lock keyword).
You should also stop relying on volatile and simply using lock to make sure that other threads "observe" updated values for your static List<..> fields.
It may be the case that the other threads don't observe a change field and thusly, for them, the field is still null - therefore you get the NullReferenceException.
About volatile
Using volatile is bad, at least in .NET. There is a 90% chance that you think you know what it is doing and it's not true and there's a 99% chance that you feel relief because you used volatile and you aren't checking for other multitasking hazards the way you should.
RX to the rescue
I strongly suggest you take a look at this wonderful thing called Reactive Extensions.
Believe me, a couple of days' research combined with the fact that you're in a perfect position to use RX will pay of, not just now but in the future as well.
You get to keep your static class, but instead of materialised values that get stored within that class you create pipes that carry information. The information flows when you want it to flow. You get to have subscribers to those pipes. The number of subscribers does not affect the overall performance of your app.
Your app will be more scalable, and more robust.
Good luck!
There are few solution for this approach:
One of them is:
It's better in Global.asax in Application_start or Session_Start (depends on your case) create Thread to call your method:
Use below code :
var t = Task.Factory.StartNew(() => {
while(true)
{
SessionManager.SetProperties();
Task.Delay(5);
}
});
Second solution is using Job Scheduler for ASP.NET (that's my ideal solution).
for more info you can check this link How to run Background Tasks in ASP.NET
and third solution is rewrite your static class as follow:
public static class SessionManager
{
public static volatile List<int> activeSessionsPCIDs;
public static volatile List<int> sessionsThatChangedStatus;
public static volatile List<SessionObject> allSessions;
static SessionManager()
{
Initialize();
}
public static void Initialize() {
var t = Task.Factory.StartNew(() => {
while(true)
{
SetProperties();
Task.Delay(5);
}
});
}
public static void SetProperties() {
SessionDataAccess sd = new SessionDataAccess();
while (true) {
allSessions = sd.GetAllSessions();
activeSessionsPCIDs = new List<int>();
sessionsThatChangedStatus = new List<int>();
foreach (SessionObject session in allSessions) {
if (session.status == 1) { //if session is active
activeSessionsPCIDs.Add(session.pcid);
}
if (session.status != session.prevStat) { //if current status doesn't match the previous status
sessionsThatChangedStatus.Add(session.pcid);
}
}
Thread.Sleep(5000);
}
}
This is a solution that is a change in approach, but I kept the solution in Web Forms, to make it more directly applicable to your use case.
SignalR is a technology that enables real-time, two way communication between server and clients (browsers), which can replace your static session data class. Below, I have implemented a simple example to demonstrate the concept.
As a sample, create a new ASP.NET Web Forms application and add the SignalR package from nuget.
Install-Package Microsoft.AspNet.SignalR
You will need to add a new Owin Startup class and add these 2 lines:
using Microsoft.AspNet.SignalR;
... and within the method
app.MapSignalR();
Add some UI elements to Default.aspx:
<div class="jumbotron">
<H3 class="MyName">Loading...</H3>
<p class="stats">
</p>
</div>
Add the following JavaScript to the Site.Master. This code references signalr, and implement client-side event handlers and initiates contact with the signalr hub from the browser. here's the code:
<script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="signalr/hubs"></script>
<script >
var hub = $.connection.sessiondata;
hub.client.someOneJoined = function (name) {
var current = $(".stats").text();
current = current + '\nuser ' + name + ' joined.';
$(".stats").text(current);
};
hub.client.myNameIs = function (name) {
$(".MyName").text("Your user id: " + name);
};
$.connection.hub.start().done(function () { });
</script>
Finally, add a SignalR Hub to the solution and use this code for the SessionDataHub implementation:
[HubName("sessiondata")]
public class SessionDataHub : Hub
{
private ObservableCollection<string> sessions = new ObservableCollection<string>();
public SessionDataHub()
{
sessions.CollectionChanged += sessions_CollectionChanged;
}
private void sessions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
Clients.All.someOneJoined(e.NewItems.Cast<string>().First());
}
}
public override Task OnConnected()
{
return Task.Factory.StartNew(() =>
{
var youAre = Context.ConnectionId;
Clients.Caller.myNameIs(youAre);
sessions.Add(youAre);
});
}
public override Task OnDisconnected(bool stopCalled)
{
// TODO: implement this as well.
return base.OnDisconnected(stopCalled);
}
}
For more information about SignalR, go to http://asp.net/signalr
Link to source code: https://lsscloud.blob.core.windows.net/downloads/WebApplication1.zip
We have a piece of code that previously worked fine and now it gets stuck, the problem seems to be runtime updates or something like it maybe?
We launch a subthread that shows a Form Dialog and gets a value, this value is returned to the main thread by a static variable in an static class and in that statement the thread gets stuck and visual studio doesn't say anything about what's happening... is there another way to return the value (in some cases there are more than one string to return)
We need to do this way specifically because of how the software we do the add-on programs for work.
Example code:
public static Cons
{
public static string inputvalue;
}
public static Funs
{
public static string GetValueString()
{
Thread threadx = new Thread(GetValueStringx);
threadx.SetApartmentState(ApartmentState.STA);
threadx.Start();
if (threadx.Join(new TimeSpan(0, 3, 0)))
{
return ComprobarLicencia(Cons.inputvalue);
}
/*because the subthread is stuck the wait time (3mins) is always
reached and the code continues here, not getting the input value :/ */
try
{
threadx.Abort();
}
catch
{
}
return "";
}
public static string GetValueStringx()
{
WindowWrapper window = new WindowWrapper(Fun.GetForegroundWindow());
FormInput formlicencia = new FormLicencia();
formlicencia.ShowDialog(window);
Cons.inputvalue = formlicencia.inputvalue; //thread gets stuck here
/*even if i comment all the above lines and i put
directly Cons.inputvalue="valx"; it gets stuck too :s */
}
}
In the end I solved it using this response in this question. Is there some way to give credit to that user? If not i would give the anwser or upvotes to someone that can explain why the subthread gets stuck accesing the static variable...
the problem only appears when making Release build and running exe file ( not from visual studio )
in all other combination either it's running from visual studio or running exe everything works fine
I'm running Function Load using backgroundWorker
Load:
while (!Request.GAMELIST.XMLReceived) ;
GameEngine.ParseGameList( Request.GAMELIST.XML );
Request.GAMELIST.XMLReceived = false;
while loop in this fragment works like delay
it should wait till XML is received from server and then continue
but it stucks in above specified situation
if I'll put MessageBox.show("here we go"); after while loop
messageBox will not appear
but if I'll put MessageBox.show("here we go"); before while loop
application will receive data until I click messagebox ok
and then everything will work fine
here is GAMELIST class implementation
public class RequestGAMELIST
{
public string XML;
public bool XMLReceived = false;
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived = true;
}
}
please provide help if you can
this is really strange thing which I can't figure out by my self
Thanks.
Yes, this code has very good odds to hang in the Release build. The JIT optimizer doesn't know that the variable might be set to true by code outside of the method. You need to tell it that, like this:
public class RequestGAMELIST
{
public volatile bool XMLReceived = false;
// etc..
}
The volatile keyword ensures that the jitter won't store the variable value in a CPU register.
That solves your problem, it is still not the right way to do it. You should use an AutoResetEvent instead. It ensures that the thread responds to the variable change is quickly as possible. And most importantly, it lets the thread block so it doesn't burn any cpu cycles.
public class RequestGAMELIST
{
public AutoResetEvent XMLReceived = new AutoResetEvent();
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived.Set();
}
}
In your thread:
XMLReceived.WaitOne();
GameEngine.ParseGameList( Request.GAMELIST.XML );
This is a bad idea:
while (!Request.GAMELIST.XMLReceived) ;
At least you should be doing something like:
while (!Request.GAMELIST.XMLReceived) {
System.Threading.Thread.Sleep(100); // Don't hog the CPU!
}
Your program runs fine in debug mode perhaps due to certain debug routines added inside the while loop which makes it run slower...