PDA

Click to See Complete Forum and Search --> : [RESOLVED] [2.0] Allow user interaction while form carrys on processing


MadCatVB
Jun 30th, 2006, 09:12 AM
Hi,

I have a windows app written in C# which is used for processing csv and excel files obtained from an ftp site.

I have most of the code written but am trying to make the interface a little less clunky. One of the buttons allows users to GET a list of files from an FTP site and download them to a specified location. This all works, however if the user clicks off the application (or anywhere else on the app) and back to it again the app window goes white and remains like that until the downloading of FTP files is complete. How can i go about making the form so that if a user clicks anywhere else the screen will refresh without any issues even if the downloads are still being processed.

Hope that made sense.

Thanks in advance,

Grant

sevenhalo
Jun 30th, 2006, 10:09 AM
Multi-Threading.

I tossed together this app so you can pull out the pieces you need:

(SuperCarcantuousFile.txt is just a file with lots of lines in it. Use whatever to make it work.)

jmcilhinney
Jun 30th, 2006, 08:19 PM
Follow the Articles -> Advanced .NET link in my signature and read the managed Threading section for all the information you could want. If you're using .NET 2.0 (please specify in future) then your life is simplified by the BackgroundWorker class.

MadCatVB
Jul 3rd, 2006, 03:10 AM
Hi,

Thanks to the both of you for posting back. I confess i am using dot net 2.0 and will change the post heading to match it. I'll read through the managed threading section and see if i can get something working. I'll also look into the background worker class.

Cheers,

Grant

MadCatVB
Jul 3rd, 2006, 06:13 AM
Jmcilhinney:

I've looked over the stuff on the BackgroundWorker Class and its exactly what i'm after. I've now managed to pupulate a listbox with available folders found in an FTP site. The interface doesn't suffer or hamper the user from doing other things while it is getting the file list. Now that i have this i'd ideally like to do the same thing for when a user downloads a number of folders from the FTP site. This works fine as function on its own but does take a while to do and stalls the UI whilst doing it.

I have the following code written but infortunately i get an error stating:

This BackgroundWorker is currently busy and cannot run multiple tasks concurrently.

when it comes to the line:

bwDownloadFtpFiles.RunWorkerAsync(bwParamArray);


private void bwDownloadFtpFiles_DoWork(object sender, DoWorkEventArgs e)
{
try
{
BackgroundWorker bw = sender as BackgroundWorker;


e.Result = downloadFtpFiles(bw, (object[])e.Argument);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

private void bwDownloadFtpFiles_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
downloadComplete = (bool)e.Result;
}

private bool downloadFtpFiles(BackgroundWorker bw, object[] args)
{
return ftpInstance.downloadFolderContents(args[0].ToString(), args[1].ToString(), (Uri)args[2]);
}

private void btnDownload_Click(object sender, EventArgs e)
{
if (clbFTPFiles.Items.Count != 0)
{
if (clbFTPFiles.CheckedItems.Count != 0)
{
pbDownload.Maximum = clbFTPFiles.CheckedItems.Count;

int i = 0; int j = 0;
pbDownload.Minimum = j;

foreach (string name in clbFTPFiles.CheckedItems)
{
object[] bwParamArray = new object[3];
bwParamArray[0] = name;
bwParamArray[1] = tbDownloadPath.Text;
bwParamArray[2] = ftpInstance.Address;

bwDownloadFtpFiles.RunWorkerAsync(bwParamArray);

if (downloadComplete)
{
lbDownloadInconsistencies.Items.Add("Folder " + name + " downloaded successfully.");
lbDownloadInconsistencies.Refresh();
i++;
}
else
{
lbDownloadInconsistencies.Items.Add("Folder " + name + " failed to download.");
lbDownloadInconsistencies.Refresh();
}
j++;
pbDownload.Value = j;
pbDownload.Refresh();
lblFilesDownloaded.Text = i.ToString();
lblFilesDownloaded.Refresh();
}
}
else
{
MessageBox.Show("Select Item(s) to download.");
}
}
else
{
MessageBox.Show("No Items Available to Download.");
}


}
}


It seems from what i can see that the RunWorkerComplete event isn't getting fired after the call is made to the BackgroundWorker. HEnce not setting the global 'downloadComplete' variable to true. But i'm not totally sure.

I'd appreciate if someone could let me know why this is happening and how it can be avoided.

Many thanks in advance.

Grant

MadCatVB
Jul 3rd, 2006, 02:30 PM
Think i have it working now. I have included a while loop before and after the call to the BackgroundWorker_DoWork function.

If the worker is busy then it does an Application.DoEvents command until it is no longer busy. Had a couple of other issues once i had done this relating to the FTPWebRequest class etc but these now seem to be ironed out.

What i would like some advice on is if using the Application.DoEvents is good practice? I have noticed there are very divided opinions on the use of it.

Cheers,

Grant

jmcilhinney
Jul 3rd, 2006, 04:56 PM
No it's not. You're already using a BackgroundWorker so that your UI will remain responsive so DoEvents is unnecessary, plus it is a relatively expensive operation. If you want a thread to wait call Sleep.

MadCatVB
Jul 4th, 2006, 04:13 AM
jmcilhinney:

Ok. I'll not use the Application.DoEvents.

If i swap the Application.DoEvents with thread.sleep(1) in the while loop my program appears to hang. This is coded into the click event of the download button and i wonder if its causing the wrong thread to sleep.

Where is the best place to put the sleep command?

Many thanks for your valuable help.

jmcilhinney
Jul 4th, 2006, 05:00 AM
I assumed you meant it was in the worker thread. Obviously you don't want to put the UI thread to sleep. If you want to do something at an interval in the UI thread then use a Timer.

MadCatVB
Jul 4th, 2006, 05:26 AM
ok, thanks for that. I'll place a timer in the UI code to deal with the backgroundworker.isbusy while loop.

I've now decided to put the foreach loop into the backgroundworker class and then try and update the UI progress bar and label via delagates as apposed to calling the bwworker thread for each individual download.

Thanks for all your help, its most appreciated.