I have my code and problem like below
step1.Visible = true;
//step1 is visible if i retrun from here but if do some work like below than its not visible until the task is completed
Thread.Sleep(5000); // some opration here Thread.Sleep is just for example
step1.Visible = true;// step1 visible here not before thread going to sleep
Here I want to show the image for each step but first step image not showing if it's followed by some long running task any idea/trick show step1 in the case of Thread.Sleep(5000)?
Use Application.DoEvents() before your Sleep (Any long running) Code.
Application.DoEvents() will processes all Windows messages currently in the message queue.
step1.Visible = true;
// Below 3 lines are not necessary. Use it only if DoEvents() doesn't work.
//step1.Invalidate();
//step1.Update();
//step1.Refresh();
// Will process the pending request of step1.Visible=true;
Application.DoEvents();
Thread.Sleep(5000);
step1.Visible = true;
I'm not sure if I understand what do you want to do but first I will use those two function : Show() and Hide()
Now you have to work with Multi Threading and comunication between Threads
Hope this could help
You should use delegates or backgroundworker process to achieve that. you can get and idea from the link below.
Animated GIF in Windows Form while executing long process
Thanks
Related
I have 2 windows. The main form and the Loading form. In the main form you send a request which will be executed. Because this takes some time, I made the Loading-form with a progress bar so that the user knows the program is working.
What I want to: The Loading-form should open itself when the process ist started and close itself when it's finished.
At the moment I have code that looks something like this:
Loading.Show();
Loading.MakeAStep(); //used for progressing the progress bar
//program is working
//finishes
Loading.Visible = false;
Loading.ResetProgress(); //Sets the value of the progress bar to 0
My problem is: The window with the progress bar opens, but there is also a label which shows "please wait". When the form opens, the progress bar works perfectly, but the label is just a hole (it really is you can look through it). When I use instead of visible = false form.Close, it works just fine with the label but I get an error when I try to start a progress in the same session.
What I want/need: Either a solution to the hole-problem, or an effective way to open and close a form several times during one session.
(Posted the solution on behalf of the question author).
The answer is in the comments: The UI blocks and I needed to Update the form with Loading.Update(); I put that between Show and MakeAStep.
As already mentioned by others, the problem is that you run your long running process in the UI thread. To avoid this, you should improve how the loading form receives the task and works on it:
The loading form should get the thing to run as a Task (maybe by a method Run(Task task). After getting this task the loading form can attach another action to it, what shall happen when the task is finished by using .ContinueWith() and simply closes itself when it reaches that point. After that it will Start() the task and call ShowDialog() on itself.
My program runs a test over a serial connection. After I click the RUN TEST button everything works great. The RUN TEST button disappears and the STOP button pops up. Data collection runs as expected. My problem is that the STOP button doesn't respond. All of my testing code is run under the RUN TEST button click event. Is this uninterruptible by my second button?
Note: I use the whateverButton.enable and whateverButton.visible properties. Is there another one I need to set to get this to work?
runButton.Enabled = false;
runButton.Visible = false;
STOPbutton.Enabled = true;
STOPbutton.Visible = true;
The rest of the program is to big to fully include.
Any help with this would greatly appreciated.
Let me guess - you disable the "Run", enable the "Stop", perform your task, reverse the enable/disable on "Run" and "Stop"?
Your issue is that the UI is not updated because the UI thread is busy running your task.
Use BackgroundWorker or Task.Run to spawn a new thread for the task, some significant refactoring may need to happen to take UI interaction out of the background thread and to support cancelling.
I just want to create a simple pause button, and perhaps another button to resume if necessary. I've been looking around and I mostly see Thread.Sleep(), which doesn't work for me because I want the pause to remain paused until the user desires.
Thread.Suspend() doesn't work because that is obsolete now.
I've also seen another solution of creating a second form, however, that doesn't seem to be working for me. Once that second form opens up, the entire program closes.
I'm not sure if this makes a difference, but my program currently uses two threads (main thread running form1 along with another thread). Ideally, everything needs to be paused.
The simpliest thing to do is to have some variable/property that the other thread can access.
Bool ShouldPause = false;
The other thread should have in it's game loop something like that :
while(true)
{
if(!ShouldPause)
{
UpdateGame();
}
Draw();
}
Then the game will proceed only when the ShouldPause variable is false.
I did it several times and it worked perfectly.
You don't want to pause the thread via some "Suspend" like functions because it will prevent from him to draw on the screen and would appear like it's not responding.
You can use Thread Signaling technique.
A good start is to take a look at ManualResetEvent Class
I have the follow button click event:
private void btnRun_Click(object sender, EventArgs e)
{
label1.Visible = true;
if (SelectDatabase())
{
if (string.IsNullOrEmpty(txtFolderAddress.Text))
MessageBox.Show("Please select a folder to begin the search.");
else
{
if (cbRecurse.Checked == false || Directory.GetDirectories(initialDirectory).Length == 0)
{
CheckSingleFolder();
}
else
{
CheckSingleFolder();
directoryRecurse(initialDirectory);
}
}
}
}
Effectively, it does a few checks and then starts some directory recursion looking for specific files. However, the very first line of code to make the label visible does not occur until after the directories have been recursed? Anybody know why this would be?
Thanks.
You're doing everything within the UI thread, which is a really bad idea - the UI doesn't get to update, react to events etc until you've finished.
You should use a background thread and update the UI with progress etc using Control.BeginInvoke, or perhaps use a BackgroundWorker.
Basically, there are two golden rules in WinForms (and similar with WPF/Silverlight):
Don't do anything which can take a significant amount of time in the UI thread
Don't touch any UI elements from any thread other than the UI thread
your whole method runs as a blocking unit currently - add an Application.DoEvents() as a workaround, but really you should be doing this kind of processing in a background thread, i.e. using a background worker.
The code is executing on the same thread which is drawing your user-interface. Therefore, while the code is executing, your UI is not being re-drawn. Once the button-click code has finished, the UI is redrawn and label1 gets drawn invisibly.
You can move your code into a separate thread using, for example, Task or BackgroundWorker. However, you cannot directly set UI properties from a different thread, so you will need to either be careful to set your UI properties from the UI thread or see this question about how to update the GUI from another thread.
The view is not updated until the code block finished. So I would propose a BackgroundWorker for the recursion part.
The explanation: the label is set to visible and it it is Invalidated (needs repainting) but the Windows message pump doesn't start repainting until it is running idle. So your code blocks it.
A simple solution is to call label1.Update() right after setting it visible.
A better solution is to move the time-consuming code to a thread (Backgroundworker).
Ok, I'm looking for something pretty simple: creating a MessageBox that doesn't stop my code.
I'm guessing I'll have to create a different thread or something? Please advise on the best way to accomplish this.
Thanks!
You could spin up another message pump by calling it on separate thread. MessageBox.Show pumps message so it is safe to do without a call to Application.Run.
public void ShowMessageBox()
{
var thread = new Thread(
() =>
{
MessageBox.Show(...);
});
thread.Start();
}
Edit:
I probably should mention that I do not recommend doing this. It can cause other problems. For example, if you have two threads pumping messages then it is possible for the message box to get stuck behind another form with no way to make it go away if the form is waiting for someone to close the message box. You really should try to figure out another way around the problem.
No, You're going to have to make your own message box form. the MessageBox class only supports behavior similar to .ShowDialog() which is a modal operation.
Just create a new form that takes parameters and use those to build up a styled message box to your liking.
Update 2014-07-31
In the spirit of maintaining clarity for anyone else who finds this through google I'd like to take a second to explain this a bit more:
Under the hood MessageBox is a fancy C# Wrapper around the Windows SDK user32.dll MessageBox Function and thus behaves exactly the same way (after converting .NET Enums into the integers that represent the same thing in the system call.
What this means is that when you call MessageBox.Show() the call is marshaled out to the OS and will block the current thread until an option is selected or the window is killed. To prevent your code from being halted you need to launch the message box on a seperate thread, but this will mean that any result that comes back from the message box (Yes / No / Ok / Cancel / Etc...) will be returned to the separate thread that was tasked to call the message box.
If you act on the result of this message box launched this way you'll have to Dispatch the result back to the UI Thread for Thread Saftey.
Alternatively you can create your own message box form in WinForms / WPF and call it with the .Show() method. Any click events on the buttons will execute on the UI Thread and you will not have to dispatch the calls back to the UI Thread to manipulate things in the UI.