Progress Bar Freezes part way - c#

So in the snippet of below I very simply look in a specific folder and copy the images from the source to the destination.
The copy is VERY fast and it works great for the first bunch of folders (maybe 20 or so) which takes a few seconds. But then the progress bar stops moving and I get a spinning mouse cursor. I can look in the destination folder and it is still processing the folders.
When it's done I get the the "Process Complete" dialog box, the progress bar is 100% and everything ran fine.
Just want to make sure the end user doesn't think it's frozen.
private void readInvoices()
{
string InvoiceFile = txtInvoiceFile.Text;
//read in the text file and get all the invoices to copy
string[] Invoices = File.ReadAllLines(InvoiceFile);
//set the max val of the progress bar
progBar.Maximum = Invoices.Length;
try
{
//for every invoice
foreach (string invoice in Invoices)
{
//Set the source and destination directories
string sourceInvFolder = string.Format(#"{0}\{1}", txtSource.Text, invoice);
string destInvFolder = string.Format(#"{0}\{1}", txtDest.Text, invoice);
DirectoryInfo SourceDI = new DirectoryInfo(sourceInvFolder);
DirectoryInfo DestDI = new DirectoryInfo(destInvFolder);
//we know we have it in the CSV but does the directory actually exist?
//if so then let's process
if (Directory.Exists(SourceDI.FullName) == true)
{
//let's copy of the files
CopyAll(SourceDI, DestDI);
RenameFolder(sourceInvFolder);
}
//inc the progress bar
progBar.Increment(1);
}
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex.Message);
}
finally
{
MessageBox.Show("Process Complete");
CleanUp();
}
}

The UI freezes because it's running in a single thread. A workaround to fix the freezing part is putting this line of code inside your loop.
Application.DoEvents();
This code checks if there are messages waiting to be processed, if there are, it processes them before proceeding to another loop. You can use a ProgressBar control to let the user see how much is processed already. If you don't want to stay with the single thread method, use a BackGroundWorker to prevent the form from appearing like it's frozen. This is multithreading, which means a separate thread is processing something while you do something else.
One thing to remember though, using the code above makes the whole looping process go slower since it has to do the checking for every loop, which means more work, in return, you get real-time progress report. The reason it looks frozen is that the loop hasn't finished yet, you'll have to let it finish first before you can do something else because it's running in a single thread.

if you want Just want to make sure the end user doesn't think it's frozen. you should use multihreading . the More suitable class for this task is BackgroundWorker
From MSDN :
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.
try to follow the example provided by msdn and put the call readInvoices() of your method in DoWork event

Your code is running on the UI thread (at least I assume so as you have a MessageBox in your catch block).
So, it will not necessarily process UI updates.
Have a look into doing the work using the TPL.
http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx

Related

Trying to use threads to save a file in the background

So I am trying to use threads to save a file in the background to prevent the main unity thread from freezing until the file is saved:
public void SaveMap() {
MapRendererBehaviour mapRendererBehaviour = GameObject.FindWithTag("MapRenderer").GetComponent<MapRendererBehaviour>();
SerializedMap serializedMap = mapRendererBehaviour.ToSerializedData();
Debug.Log("test");
_saveMapThread = new Thread(() => {
string saveMapJson = JsonConvert.SerializeObject(serializedMap);
File.WriteAllText(_saveMapFilePath, saveMapJson);
});
}
For some reason the thread code does not seem to be executing because the file is not getting saved. If I comment out the thread creation and just leave the body of the thread in there, the file saves properly.
Anyone know what I might be doing wrong here (I assume I am doing something dumb as I have never tried to use threads before).
This might be a shot in the dark but if you are using named threads instead of tasks you normally have to say ThreadName.Start() after so for example after declaring the thread say:
_saveMapThread.Start();

What is the difference between these two methods for pausing/resuming threads?

I have a multithreaded application which is used to extract data from a website. I wanted to be able to pause and resume multiple threads from the UI. After searching on the web I came to know about two approaches that I can use to control (pause/resume) my threads.
Using Monitor class.
Using EventWaitHandle and ManualResetEvent class.
What I did:
I have a function named GetHtml that simply returns the html of the website. I am just showing the fraction part of this function for brevity.
public string GetHtml(string url, bool isProxy = false)
{
string result = "";
ExecutionGateway();
//->> EXTRA CODE FOR FETCHING HTML
return result;
}
I have a function ControlTasks used to control threads from UI, below I have explained the ControlTasks function using both thread control approaches using the Monitor class as well as the EventWaitHandle class (I will also briefly explain the working of the function ExecutionGateway).
1. Using the Monitor class
private object taskStopper = new object();
public bool ControlTasks(bool isPause)
{
try
{
if (isPause)
{
Monitor.Enter(taskStopper);
}
else
{
Monitor.Exit(taskStopper);
}
return true;
}
catch (Exception ex)
{
Logger.Instance.WriteLog("ControlTasks:", ex, Logger.LogTypes.Error);
return false;
}
}
ControlTasks is called from the UI where if isPause is true the exclusive lock is used on object taskStopper else releases the lock, Now here comes the function ExecutionGateway which is used to acquire lock on object taskStopper but it does nothing as the code below shows.
private void ExecutionGateway()
{
lock(taskStopper){ }
}
In this way all running threads enters waiting state when isPause is true in ControlTasks as taskStopper is exclusively locked and if isPause is false all threads resumes their processing.
2. Using the EventWaitHandle class
private EventWaitHandle handle = new ManualResetEvent(true);
public bool ControlTasks(bool isPause)
{
try
{
if (isPause)
{
handle.Reset();
}
else
{
handle.Set();
}
return true;
}
catch (Exception ex)
{
Logger.Instance.WriteLog("ControlTasks:", ex, Logger.LogTypes.Error);
return false;
}
}
This code also fundamentally does the same job, where the event state is signaled/non-signaled depending on the isPause parameter. Now, the corresponding ExecutionGateway method.
private void ExecutionGateway()
{
handle.WaitOne(Timeout.Infinite);
}
Problem:
What is the difference between these two approaches, is one better than the other? Are there any other ways to do this?
The main problem I have faced many times is if I use either of the above methods and I have 100 threads; when I pause them, then resume them after 5 or more minutes, the UI starts hanging. The UI is terrifically unresponsive. It gets updated but keeps on hanging and I keep getting the message "Not Responding" at each interval. One thing I want to mention each thread extracts data and notifies the UI about the data fetched through event handling. What could be the reason of this unresponsiveness? Is it a problem with my approach(es)?
I think it's always desirable to use a construct that communicates your intent clearly. You want a signal to other threads that they should wait (i.e. stop doing what they're doing) until you signal to them that they can start again. You have one controlling thread (your UI) and potentially many threads doing work and marshalling results back to the UI.
Approach 1 isn't ideal because locks (at least in my experience) are most often used to protect a resource that isn't suitable for use in multi threaded code. For example, writing to a shared field.
Approach 2 makes much more sense, a manual reset event functions like a gate: open the gate and things can pass through, close it and they can't. That's exactly the behaviour you're looking for and I think most developers would understand quite quickly that that's your intent.
As for your second problem, it sounds like you're getting waves of messages clogging the UI. If you stop all 100 of your threads then start them at the same time, there's a good chance they're going to finish their work quite close together and all be trying to send the result of their work to the UI thread. To solve that you could try staggering the work when you restart or use fewer threads. Another option would be to aggregate results and only dispatch the the UI every x seconds - but that's a bit more work.
In Option 1, using the Monitor class means that only one thread owns the exclusive lock of the monitor object at a time. This means that of your 100 threads, only 1 is processing at a time, which kind of defeats the purpose of using threads. It also means that your GUI thread has to wait until the current worker thread has finished before it can obtain the lock.
The ManualResetEvent is a much better choice as it is used to signal between threads, rather than protect against multiple thread access.
I do not know why your GUI is so unresponsive using the second option, but I do not think it is related to your manual reset event. More likely you have a different problem where the GUI thread is getting swamped. You suggest you have 100 threads all firing notification events to the GUI which would seem a likely culprit.
What happens if you debug your app, and just randomly break when your GUI is unresponsive? Doing this many times should show what your GUI thread is up to and where the bottleneck is.

Thread to process infinite work

Hello guys,
I created a thread that scanning for some files on the desktop and do some actions with that. The problem is the process of this thread happens only once - when the scanning of files done.
My purpose with that thread is to scan directories anytime without stopping but without creating an overflow of CPU usage. I want to use a smart way to prevent stopping of this scanning.
The action with the files is to check if there is a specific content that need to be there, I am scanning for this content in all files.
I tried to use the while infinite loop style:
public void bwScanning()
{
while(true)
{
// the whole code of scanning goes here.
}
}
But It's too risky because of the pumping system resources with that loop.
I thought about a few things how to create smarter code:
Run a thread by timer with delay of 20 seconds. But then, i don't know what is the amount of files and how much time takes for the process of scanning dirs to be done..
maybe create number of threads - after the first thread finished, create a new one.
I think it's very ridiculous to use this way because of the new creation and memory usage.
Some people that encountered with the same problem can advise me?
If you want to periodically scan the files but you do not know how long it takes something real simple is to put a sleep at the end of your while loop like this:
public void bwScanning()
{
while(true)
{
// the whole code of scanning goes here.
Thread.Sleep(20000); // sleep 20sec
}
}
Another option is to use a timer to run your scan function in periodic intervals and keep a flag indicating whether you are still in the process of scanning and simply return if you are:
bool isProcessing;
public void bwScanning()
{
if (isProcessing) return;
isProcessing = true;
try {
// the whole code of scanning goes here.
}
finally {
// in case your processing code throws an exception this ensures you are resetting the flag
isProcessing = false;
}
}
A simple thread.sleep(1) should cut it, I have a software with several such loops running at once and a simple 1 ms sleep was enough to send the cpu usage back to under 1%.
How dow you stop the thread? Assumed you use an event object to signal shutdown, I'd suggest something like:
public void bwScanning()
{
while( ! stopEvent.WaitOne(20*1000,false))
{
// the whole code of scanning goes here.
}
}

calling dialog and getting values from it in backgroundworker?

I am working on a WPF project where I have to import data from a lot of single files.
The actual importing of those files and the data in them is being done in a backgroundworker doWork method.
It works like a charm, does the job and updating a progress bar also works perfectly.
Now though, depending on what I encounter in those files, I occasionally need to get a decision from the User before I can proceed processing the current file.
What is the best way to open a window/dialog, getting the values set in there back into the backgroundworker.doWork method and continue processing?
Is that even possible with a backgroundworker or do I need to keep that processing logic in the main/UI thread and update the progress bar from there somehow?
I hope some of you can give me some hints or point me to other resources since I have not found much useful information for my specific problem.
Background worker works in a different thread. You can not invoke UI directly from a background thread. One way of achiving what you are trying to do is by using a flag and Dispatcher to invoke UI for user input
bool WaitFor_Input = false; //flag to indicate user input status
private void ThreadRun()
{
//THIS IS IN Background worker thread
//do task
WaitFor_Input = true;
//ask for user input
Dispatcher.BeginInvoke(new Action(Show_Dialogue), null);
while (WaitFor_Input); //Background worker waits untill user input is complete
//continue further processing
}
private void Show_Dialogue()
{
//THIS IS IN UI THREAD
//show your dialogue box here, update data variables
//finally set
WaitFor_Input = false;
}
Keeping processing logic in a background thread is actually a good idea.
You can call the ShowDialog of an OpenFileDailog class on a new Thread or BackgroundWorker( this will also create a new thread)
But when you want to pass or update any property or control that is running on the main thread you will need to use the Disptacher like this
Dispatcher.BeginInvoke(new Action(() => { YourMethodThatUpdatesSomething(); }));

Threading in Form_Load - Application now hangs suddenly

Sorry for the lengthy post, I just want to illustrate my situation as best as possible. Read the items in bold and check the code if you want the quick gist of the issue.
I use ClickOnce to deploy a C# application, and have opted to have my application check for updates manually using the ApplicationDeployment Class rather than letting it do the update checking for me.
The program is a specialized network scanner that searches for network devices made by the company I work for. Once the main window is loaded, a prompt is displayed asking if the user would like to scan the network. If they say Yes, a scan begins which can take a minute or two to complete depending on their network settings; otherwise it just waits for the user to do some action.
One of the last things I do in Form_Load is create a new thread that checks for updates. This had all been working fine for several months through about 12 releases and has suddenly stopped working. I didn't change the update code at all, nor change the sequence of what happens when the app starts.
In staring at the code, I think I see why it is not working correctly and wanted to confirm if what I think is correct. If it is, it begs the question as to why it DID work before - but I'm not too concerned with that either.
Consider the following code:
frmMain.cs
private void Form1_Load(object sender, EventArgs e)
{
// set up ui, load settings etc
Thread t = new Thread(new ParameterizedThreadStart(StartUpdateThread));
t.Start(this);
}
private void StartUpdateThread(object param)
{
IWin32Window owner = param as IWin32Window;
frmAppUpdater.CheckForUpdate(owner);
}
frmAppUpdater.cs
public static void CheckForUpdate(IWin32Window owner)
{
if (ApplicationDeployment.IsNetworkDeployed) {
Console.WriteLine("Going to check for application updates.");
parentWindow = owner;
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
ad.CheckForUpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_CheckForUpdateProgressChanged);
ad.CheckForUpdateAsync();
// CAN/WILL THE THREAD CREATED IN FORM1_LOAD BE TERMINATED HERE???
}
}
When the CheckForUpdateAsync() callback completes, if no update is available the method call simply returns; if an update IS available, I use a loop to block until 2 things occur: The user has dismissed the "Would you like to scan prompt" AND no scan is currently running.
The loop looks like this, which takes place in ad_CheckForUpdateCompleted:
while (AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) {
System.Threading.Thread.Sleep(5000);
}
I sleep for 5 seconds because I figured this was happening in a separate thread and it has seemed to work well for a while.
My main question about the above code is:
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does the thread I created in Form1_Load terminate (or might it terminate)? I suspect it may because the subsequent Async call causes the method to return, and then start another thread?
The only reason I am confused is because this method WAS working for so long without hanging the application and now all of the sudden it hangs and my best effort at debugging revealed that it was that Sleep call blocking the app.
I'd be happy to post the full code for frmAppUpdater.cs if it would be helpful.
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does
the thread I created in Form1_Load terminate (or might it terminate)?
If the CheckForUpdateAsync() call is asynchronous then yes, the thread will terminate, no it won't otherwise.
If you suspect the Sleep to have caused the application hang then these two variables AppGlobals.ScanInProgress and AppGlobals.ScanPromptVisible are probably always set to true! You should start looking at the code that is setting them to true and see what is going on there.
In order to avoid an application hang, you could introduce a variable to avoid sleeping indefinitely:
int nTrials = 0;
while ((AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) && (nTrials < 5)) {
System.Threading.Thread.Sleep(5000);
nTrials++;
}
// Check the results and act accordingly
I personally do not like using Sleep for thread synchronization. .NET offers a bunch of classes that are perfect for thread synchronization, WaitHandle being one of them.
See this post at Asynchronous Delegates Vs Thread/ThreadPool?
your form load method seems to be doing synchronous work. you mention that you are using clickonce deployment. Has the binary location changed after the previous release or has permissions on this resource changed. Looks like the work (checkupdates) in the Thread is never finishing and is never handed back to the form.
as an immediate fix, I would change the Thread approach to Delegate - if you use delegate, then this becomes less of a customer issue (the form will respond to end user) but the underlying problem remains.
as the next step, i would go through http://msdn.microsoft.com/en-us/library/ms229001.aspx and do the troubleshoot

Categories

Resources